Android 匿名內部類造成的記憶體洩漏
阿新 • • 發佈:2019-01-31
我們在寫專案的時候,很容易在一個Actiivty下面利用如下程式碼:
private Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
// do something
}
};
這樣寫很容易造成記憶體洩漏。因為匿名內部類handler是持有外面Activity的引用的,handler又是將message傳送到訊息佇列中的,因此message就持有handler的引用。在訊息佇列中是按順序被處理的,如有message正在等待訊息佇列處理它,此時Activity執行了finish,Activity不會被銷燬的,因為message還沒有做處理,handler不會被回收,Activity也不會被回收,那麼就會記憶體洩漏。
遇到這種情況有二種解決記憶體洩漏的方法,
第一:
在Activity 的 onDestroy方法中執行 handler..removeCallbacksAndMessages(null);
將正在等待處理的meessage remove掉。
第二:
利用靜態內部類不隱性持有外部類引用的特點,如下
此時,如果靜態內部類需要用到外面的類,那麼讓handler持有一個弱引用的activity,這樣就不會造成記憶體洩漏。private final Handler handler = new MyHandler(this); private static class MyHandler extends Handler{ private final WeakReference<xxxActivity> ref; public MyHandler(xxxActivity activity) { ref = new WeakReference<xxxActivity>(activity); } @Override public void handleMessage(Message msg) { if (ref == null) { return; } xxxActivity activity = ref.get(); //acitivity被回收 if (activity==null) { return; } // next ... } }
總結:
a 匿名內部類、非靜態內部類都會隱性持有外部類引用,而靜態內部類和匿名類的靜態例項是不會持有外部類引用的。
b 遇到生命週期比activity長的情形,記憶體洩漏一定是個隱患。
c 儘量新建一個檔案定義類亦或者利用弱引用拿到外部類引用。