Dalam aplikasi Android, apakah ada yang salah dengan pendekatan berikut:
public class MyApp extends android.app.Application {
private static MyApp instance;
public MyApp() {
instance = this;
}
public static Context getContext() {
return instance;
}
}
dan menyebarkannya di mana-mana (misalnya SQLiteOpenHelper) di mana konteks diperlukan (dan tentu saja tidak bocor)?
android
android-context
yanchenko
sumber
sumber
<application>
node file AndroidManifest.xml untuk menyertakan definisi atribut berikut:android:name="MyApp"
. MyApp harus di bawah paket yang sama dengan referensi manifes Anda.Jawaban:
Ada beberapa masalah potensial dengan pendekatan ini, meskipun dalam banyak keadaan (seperti contoh Anda) itu akan bekerja dengan baik.
Khususnya Anda harus berhati-hati ketika berurusan dengan apa pun yang berhubungan dengan
GUI
yang membutuhkanContext
. Misalnya, jika Anda memasukkan Konteks aplikasi ke dalamLayoutInflater
Anda akan mendapatkan Pengecualian. Secara umum, pendekatan Anda sangat baik: ini adalah praktik yang baik untuk menggunakan diActivity's
Context
dalam ituActivity
, danApplication Context
ketika melewati konteks di luar ruang lingkupActivity
untuk menghindari kebocoran memori .Juga, sebagai alternatif untuk pola Anda Anda dapat menggunakan shortcut memanggil
getApplicationContext()
padaContext
objek (seperti Activity) untuk mendapatkan Konteks Aplikasi.sumber
LayoutInflator
hanya dengan bekerja untuk saya. Pasti sudah berubah dalam tiga tahun terakhir.Dalam pengalaman saya, pendekatan ini seharusnya tidak perlu. Jika Anda memerlukan konteks untuk apa pun, Anda biasanya dapat memperolehnya melalui panggilan ke View.getContext () dan menggunakan yang
Context
diperoleh di sana, Anda dapat menghubungi Context.getApplicationContext () untuk mendapatkanApplication
konteks. Jika Anda mencoba untuk mendapatkanApplication
konteks ini dari sebuah,Activity
Anda selalu dapat memanggil Activity.getApplication () yang seharusnya dapat diteruskan sesuaiContext
kebutuhan untuk panggilanSQLiteOpenHelper()
.Secara keseluruhan sepertinya tidak ada masalah dengan pendekatan Anda untuk situasi ini, tetapi ketika berhadapan dengan
Context
pastikan Anda tidak membocorkan memori di mana pun seperti yang dijelaskan di blog resmi Google Android Developers .sumber
Beberapa orang bertanya: bagaimana mungkin singleton mengembalikan pointer nol? Saya menjawab pertanyaan itu. (Saya tidak bisa menjawab dalam komentar karena saya perlu mengirim kode.)
Ini dapat mengembalikan nol di antara dua peristiwa: (1) kelas dimuat, dan (2) objek kelas ini dibuat. Ini sebuah contoh:
Mari kita jalankan kodenya:
Baris kedua menunjukkan bahwa Y.xinstance dan X.yinstance adalah null ; mereka nol karena variabel X.xinstance ans Y.yinstance dibaca ketika mereka nol.
Bisakah ini diperbaiki? Iya,
dan kode ini tidak menunjukkan anomali:
TAPI ini bukan opsi untuk
Application
objek Android : programmer tidak mengontrol waktu ketika itu dibuat.Sekali lagi: perbedaan antara contoh pertama dan yang kedua adalah bahwa contoh kedua menciptakan sebuah instance jika pointer statis adalah nol. Tapi programmer tidak dapat membuat satu objek aplikasi Android sebelum sistem memutuskan untuk melakukannya.
MEMPERBARUI
Satu lagi contoh membingungkan di mana bidang statis yang diinisialisasi terjadi
null
.Main.java :
Dan Anda mendapatkan:
Perhatikan bahwa Anda tidak dapat memindahkan deklarasi variabel statis satu baris ke atas, kode tidak akan dikompilasi.
sumber
Kelas Aplikasi:
Deklarasikan Aplikasi di AndroidManifest:
Pemakaian:
sumber
Anda mencoba membuat pembungkus untuk mendapatkan Konteks Aplikasi dan ada kemungkinan "
null
" itu mengembalikan pointer.Sesuai pemahaman saya, saya kira pendekatan yang lebih baik untuk memanggil-salah satu dari 2
Context.getApplicationContext()
atauActivity.getApplication()
.sumber
Itu pendekatan yang bagus. Saya menggunakannya sendiri juga. Saya hanya akan menyarankan untuk mengganti
onCreate
mengatur singleton daripada menggunakan konstruktor.Dan karena Anda menyebutkan
SQLiteOpenHelper
:onCreate ()
Anda dapat membuka database juga.Secara pribadi saya pikir dokumentasi salah dengan mengatakan bahwa Biasanya tidak perlu untuk subkelas Aplikasi . Saya pikir kebalikannya benar: Anda harus selalu subkelas Aplikasi.
sumber
Saya akan menggunakan Konteks Aplikasi untuk mendapatkan Layanan Sistem di konstruktor. Ini memudahkan pengujian & manfaat dari komposisi
Kelas uji kemudian akan menggunakan konstruktor yang kelebihan beban.
Android akan menggunakan konstruktor default.
sumber
Saya suka, tapi saya akan menyarankan singleton sebagai gantinya:
sumber
new
menggunakan Aplikasi sendiri (dengan kemungkinan pengujian unit). Sistem operasi akan melakukan itu. Anda seharusnya juga tidak memiliki konstruktor. Itu untuk apaonCreate
.Saya menggunakan pendekatan yang sama, saya sarankan untuk menulis singleton sedikit lebih baik:
tapi saya tidak menggunakan di mana-mana, saya menggunakan
getContext()
dan digetApplicationContext()
mana saya bisa melakukannya!sumber