Saya mendapat peringatan dalam kode saya yang menyatakan:
Kelas AsyncTask ini harus statis atau kebocoran mungkin terjadi (anonim android.os.AsyncTask)
Peringatan lengkapnya adalah:
Kelas AsyncTask ini harus statis atau kebocoran mungkin terjadi (anonim android.os.AsyncTask) Bidang statis akan membocorkan konteks. Kelas dalam non-statis memiliki referensi implisit ke kelas luarnya. Jika kelas luar itu misalnya Fragmen atau Aktivitas, maka referensi ini berarti bahwa pawang / pemuat / tugas yang sudah berjalan lama akan memegang referensi ke aktivitas yang mencegahnya mengumpulkan sampah. Demikian pula, referensi lapangan langsung ke aktivitas dan fragmen dari instance yang berjalan lebih lama ini dapat menyebabkan kebocoran. Kelas ViewModel tidak boleh mengarah ke Tampilan atau Konteks non-aplikasi.
Ini kode saya:
new AsyncTask<Void,Void,Void>(){
@Override
protected Void doInBackground(Void... params) {
runOnUiThread(new Runnable() {
@Override
public void run() {
mAdapter.notifyDataSetChanged();
}
});
return null;
}
}.execute();
Bagaimana saya memperbaikinya?
sumber
myActivity.getApplication()
konstruktor pribadi untuk Singleton, untuk menginisialisasi kelas RoomDB dan kelas lainnya). ViewModels saya mendapatkan instance Singleton sebagai referensi pribadi untuk melakukan beberapa operasi pada DB. Jadi, ViewModels mengimpor paket Singleton, dan jugaandroid.app.Application
, salah satunyaandroid.app.Activity
. Karena "Singleton" tidak perlu mengimpor ViewModels tersebut agar berfungsi, meskipun demikian, mungkinkah terjadi kebocoran memori?Jawaban:
Kelas dalam non-statis memegang referensi ke kelas yang berisi. Ketika Anda mendeklarasikan
AsyncTask
sebagai kelas dalam, itu mungkin hidup lebih lama daripada yang mengandungActivity
kelas yang . Ini karena referensi implisit ke kelas yang mengandung. Ini akan mencegah aktivitas dari pengumpulan sampah, karenanya memori bocor.Untuk mengatasi masalah Anda, gunakan kelas bersarang statis alih-alih anonim, lokal, dan kelas dalam atau gunakan kelas tingkat atas.
sumber
Cara menggunakan kelas AsyncTask bagian dalam statis
Untuk mencegah kebocoran, Anda dapat membuat kelas dalam statis. Masalahnya adalah Anda tidak lagi memiliki akses ke tampilan UI variabel aktivitas atau anggota. Anda dapat mengirimkan referensi ke
Context
tetapi kemudian Anda menjalankan risiko yang sama dari kebocoran memori. (Android tidak dapat mengumpulkan sampah Aktivitas setelah ditutup jika kelas AsyncTask memiliki referensi yang kuat untuk itu.) Solusinya adalah membuat referensi yang lemah ke Aktivitas (atau apa pun yangContext
Anda butuhkan).Catatan
AsyncTask
tutorial utama di luar sana yang masih belum menanganinya (lihat di sini , di sini , di sini , dan di sini ).AsyncTask
kelas atas. Kelas dalam statis pada dasarnya sama dengan kelas tingkat atas di Jawa.Jika Anda tidak membutuhkan Kegiatan itu sendiri tetapi tetap menginginkan Konteks (misalnya, untuk menampilkan a
Toast
), Anda dapat meneruskan referensi ke konteks aplikasi. Dalam hal iniAsyncTask
konstruktor akan terlihat seperti ini:Kotlin
Di Kotlin, jangan memasukkan
inner
kata kunci untuk kelas dalam. Ini menjadikannya statis secara default.sumber
onPostExecute
metode saya lagi dalam kode di atas. Anda dapat melihat bahwa saya memperbarui UI diTextView
sana. Cukup gunakanactivity.findViewById
untuk mendapatkan referensi ke elemen UI apa pun yang perlu Anda perbarui.activity.isFinishing()
cek dan mungkin menggantinya denganfragment.isRemoving()
cek. Saya belum banyak bekerja dengan fragmen.AsyncTask
konstruktor Anda, Anda meneruskan referensi ke kelas luar Anda. Dan di dalamdoInBackground()
Anda bisa mendapatkan referensi dengan kelas luarMyOuterClass ref = classReference.get()
. Periksanull
. (2) DionPostExecute()
Anda hanya memperbarui UI dengan hasil dari tugas latar belakang. Sama seperti waktu lainnya Anda memperbarui UI. Pemeriksaanactivity.isFinishing()
hanya untuk memastikan bahwa aktivitas belum mulai selesai, dalam hal ini tidak ada gunanya untuk memperbarui UI.AsyncTask
Kelas ini seharusnya statis atau kebocoran mungkin terjadi karenaActivity
dihancurkan,AsyncTask
(keduanyastatic
ataunon-static
) masih berjalannon-static
(AsyncTask
) kelas, itu akan memiliki referensi ke kelas luar (Activity
).Garbage Collected
akan merilisnya. Jika suatu objek tidak digunakan danGarbage Collected
tidak dapat melepaskannya => kebocoran memori=> Jika
AsyncTask
ininon-static
,Activity
tidak akan merilis acara itu hancur => kebocoranSolusi untuk pembaruan UI setelah menjadikan AsyncTask sebagai kelas statis tanpa kebocoran
1) Gunakan
WeakReference
jawaban seperti @Suragch2) Kirim dan hapus
Activity
referensi ke (dari)AsyncTask
sumber
onDestroy()
tidak dijamin dipanggil setiap saat