我們?cè)趯?xiě)Android程序的時(shí)候經(jīng)常會(huì)使用到Handler,最常用的初始化Handler的方式如下:
private Handler handler = new Handler(){
@Override
public void handleMessage(@NonNull Message msg) {
//邏輯處理
}
};
在這樣寫(xiě)完之后我不知道大家有沒(méi)有注意到Android Studio給了我們一個(gè)警告提示:
This Handler class should be static or leaks might occur...
Since this Handler is declared as an inner class, it may prevent the outer class from being garbage collected.
If the Handler is using a Looper or MessageQueue for a thread other than the main thread, then there is no
issue. If the Handler is using the Looper or MessageQueue of the main thread, you need to fix your Handler
declaration, as follows: Declare the Handler as a static class; In the outer class, instantiate a WeakReference
to the outer class and pass this object to your Handler when you instantiate the Handler; Make all references
to members of the outer class using the WeakReference object.
上面這段警告的大致意思就是說(shuō):Handler被聲明成了內(nèi)部類(lèi),而如果我們又使用了主線程的Looper或者M(jìn)essageQueue她我,那么可能會(huì)導(dǎo)致外部類(lèi)也就是Activity無(wú)法被垃圾回收器回收而造成內(nèi)存泄漏等缀。建議是使用靜態(tài)Handler類(lèi)疼燥,并在外部類(lèi)初始化WeakReference對(duì)象茉稠,然后傳入到Handler中,然后使用這個(gè)WeakReference對(duì)象。
用代碼來(lái)說(shuō)明就是這樣:
private LodingHandler handler = new LodingHandler(new WeakReference<LodingActivity>(this));
static class LodingHandler extends Handler{
WeakReference<LodingActivity> activityWeakReference;
public LodingHandler(WeakReference<LodingActivity> activityWeakReference){
this.activityWeakReference = activityWeakReference;
}
@Override
public void handleMessage(@NonNull Message msg) {
super.handleMessage(msg);
LodingActivity activity = activityWeakReference.get();
if (null != activity){
//邏輯處理
}
}
}
那么造成這個(gè)問(wèn)題的原因是:
由于在Java中非靜態(tài)匿名內(nèi)部類(lèi)將保存對(duì)外部類(lèi)的隱式引用蜡镶,而靜態(tài)內(nèi)部類(lèi)則不會(huì)。安卓框架的工程師 Romain Guy曾說(shuō)明過(guò)他在 Android 代碼庫(kù)中發(fā)現(xiàn)了一些內(nèi)存泄漏恤筛,Message 有一個(gè)對(duì) Handler 的引用官还,當(dāng)它是內(nèi)部的和非靜態(tài)的時(shí)候,它有一個(gè)對(duì)外部 this 的引用(例如一個(gè) Activity毒坛。) 如果 Message 在隊(duì)列中長(zhǎng)時(shí)間存在(例如妻枕,在發(fā)布延遲消息時(shí)非常容易發(fā)生這種情況) ,則保留對(duì) Activity 的引用并“泄漏”所有視圖和資源粘驰。