Handler導(dǎo)致Activity內(nèi)存泄漏

我們用原來的辦法使用Handler時會有下面一段溫馨的提示:

This Handler class should be static or leaks might occur
下面是更詳細的說明(Android Studio上的警告,不知道Eclipse上是否相同)

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.

大概意思就是:

一旦Handler被聲明為內(nèi)部類,那么可能導(dǎo)致它的外部類不能夠被垃圾回收。如果Handler是在其他線程(我們通常成為worker thread)使用Looper或MessageQueue(消息隊列),而不是main線程(UI線程),那么就沒有這個問題。如果Handler使用Looper或MessageQueue在主線程(main thread),你需要對Handler的聲明做如下修改:

聲明Handler為static類;在外部類中實例化一個外部類的WeakReference(弱引用)并且在Handler初始化時傳入這個對象給你的Handler;將所有引用的外部類成員使用WeakReference對象。

解決方案:
private CopyFileHandler mHandler;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_appstart);
mHandler = new CopyFileHandler(this);
startCopyDBThread();
}

private void startCopyFileThread(){
Log.d(TAG, "startCopyDBThread");
new Thread(new Runnable() {
@Override
public void run() {
//DO SOMETHING LIKE: copyDBFile();
Message msg=mHandler.obtainMessage();
mHandler.sendMessage(msg);
}
}).start();
}

private static class CopyFileHandler extends Handler {
WeakReference<AppStartActivity> mActivity;
public CopyFileHandler(AppStartActivity activity) {
mActivity = new WeakReference<>(activity);
}

public void handleMessage(Message msg) {
    final AppStartActivity activity = mActivity.get();
   //handle you message here!
}

}
那么為什么不這樣做會引發(fā)內(nèi)存泄漏呢?
這與幾個關(guān)鍵詞有關(guān):內(nèi)部類、Handler的消息循環(huán)(Looper)、Java垃圾回收機制。
需要強調(diào)一下,并不是每次使用Handler都會引發(fā)內(nèi)存泄漏,這里面有一定的幾率,需要滿足特定條件才會引起泄漏。
內(nèi)部類會有一個指向外部類的引用。
垃圾回收機制中約定,當內(nèi)存中的一個對象的引用計數(shù)為0時,將會被回收。
Handler作為Android上的異步消息處理機制(好吧,我大多用來進行worker thread與UI線程同步),它的工作是需要Looper和MessageQueue配合的。簡單的說,要維護一個循環(huán)體(Looper)處理消息隊列(MessageQueue)。每循環(huán)一次就從MessageQueue中取出一個Message,然后回調(diào)相應(yīng)的消息處理函數(shù)。

如果,我是說如果,循環(huán)體中有消息未處理(Message排隊中),那么Handler會一直存在,那么Handler的外部類(通常是Activity)的引用計數(shù)一直不會是0,所以那個外部類就不能被垃圾回收。很多人會遇到activity的onDestroy方法一直不執(zhí)行就是這個原因。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容