1. 程式人生 > >Android 匿名內部類造成的記憶體洩漏

Android 匿名內部類造成的記憶體洩漏

我們在寫專案的時候,很容易在一個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掉。

第二:

利用靜態內部類不隱性持有外部類引用的特點,如下

    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 ...
        }
    }
此時,如果靜態內部類需要用到外面的類,那麼讓handler持有一個弱引用的activity,這樣就不會造成記憶體洩漏。

總結:

a 匿名內部類、非靜態內部類都會隱性持有外部類引用,而靜態內部類和匿名類的靜態例項是不會持有外部類引用的。

b 遇到生命週期比activity長的情形,記憶體洩漏一定是個隱患。

c 儘量新建一個檔案定義類亦或者利用弱引用拿到外部類引用。