Saya sedang mengembangkan aplikasi Android 2.3.3 dengan sebuah layanan. Saya memiliki ini di dalam layanan itu untuk berkomunikasi dengan aktivitas Utama:
public class UDPListenerService extends Service
{
private static final String TAG = "UDPListenerService";
//private ThreadGroup myThreads = new ThreadGroup("UDPListenerServiceWorker");
private UDPListenerThread myThread;
/**
* Handler to communicate from WorkerThread to service.
*/
private Handler mServiceHandler;
// Used to receive messages from the Activity
final Messenger inMessenger = new Messenger(new IncomingHandler());
// Use to send message to the Activity
private Messenger outMessenger;
class IncomingHandler extends Handler
{
@Override
public void handleMessage(Message msg)
{
}
}
/**
* Target we publish for clients to send messages to Incoming Handler.
*/
final Messenger mMessenger = new Messenger(new IncomingHandler());
[ ... ]
}
Dan di sini,, final Messenger mMessenger = new Messenger(new IncomingHandler());
saya mendapatkan peringatan Lint berikut:
This Handler class should be static or leaks might occur: IncomingHandler
Apa artinya?
Jawaban:
Jika
IncomingHandler
kelas tidak statis, itu akan memiliki referensi keService
objek Anda .Handler
objek untuk utas yang sama semua berbagi objek Looper umum, yang mereka kirimi pesan dan baca.Karena pesan mengandung target
Handler
, selama ada pesan dengan target handler dalam antrian pesan, handler tidak dapat dikumpulkan sebagai sampah. Jika pawang tidak statis, AndaService
atauActivity
tidak dapat mengumpulkan sampah, bahkan setelah dihancurkan.Hal ini dapat menyebabkan kebocoran memori, setidaknya untuk beberapa waktu - selama pesan tetap dalam antrian. Ini tidak banyak masalah kecuali Anda mengirim pesan yang lama tertunda.
Anda dapat membuat
IncomingHandler
statis dan memilikiWeakReference
layanan Anda:Lihat posting ini oleh Romain Guy untuk referensi lebih lanjut
sumber
get()
akan mengembalikan nol ketika objek yang direferensikan adalah gc-ed. Dalam hal ini, ketika layanan mati.Seperti orang lain telah menyebutkan peringatan Lint adalah karena potensi kebocoran memori. Anda dapat menghindari peringatan Lint dengan melewatkan
Handler.Callback
ketika membangunHandler
(yaitu Anda tidak subkelasHandler
dan tidak adaHandler
kelas dalam non-statis):Seperti yang saya pahami, ini tidak akan menghindari potensi kebocoran memori.
Message
objek memegang referensi kemIncomingHandler
objek yang memegang referensiHandler.Callback
objek yang memegang referensi keService
objek. Selama ada pesan dalamLooper
antrian pesan, makaService
tidak akan menjadi GC. Namun, itu tidak akan menjadi masalah serius kecuali jika Anda memiliki pesan lama dalam antrian pesan.sumber
Berikut adalah contoh umum menggunakan kelas referensi lemah dan pengendali statis untuk menyelesaikan masalah (seperti yang direkomendasikan dalam dokumentasi Lint):
sumber
Myclass
harus dinyatakan sebagaipublic Handler getHandler()
bukanpublic void
Cara ini bekerja dengan baik untuk saya, menjaga kode tetap bersih dengan menjaga di mana Anda menangani pesan di kelas dalamnya sendiri.
Pawang yang ingin Anda gunakan
Kelas batin
sumber
Dengan bantuan jawaban @ Sogger, saya membuat Handler generik:
Antarmuka:
Saya menggunakannya sebagai berikut. Tapi saya tidak yakin 100% apakah ini aman bocor. Mungkin seseorang bisa berkomentar tentang ini:
sumber
Saya tidak yakin tetapi Anda dapat mencoba menginternalisasi handler ke null di onDestroy ()
sumber
Saya bingung. Contoh yang saya temukan menghindari properti statis sepenuhnya dan menggunakan utas UI:
Hal yang saya sukai dari solusi ini adalah tidak ada masalah dalam mencoba memadukan variabel kelas dan metode.
sumber