Activity在onDestroy後,Activity對象的WeakReference並不爲空

問題描述:

使用普通內部類或匿名類開啓線程執行耗時任務,若任務沒有結束而Activity銷燬,那麼,因爲內部類或匿名類對外部類Activity持有強引用,會導致Activity對象一直無法釋放,從而無法回收,導致內存泄露。

於是,改成外部類或內部靜態類後,對Activity不產生強引用了,那麼,線程任務結束時,如何回調給Activity呢?

保存Activity的WeakReference,即弱引用。通過WeakReference.get()來判斷Activity對象是否存在,然後進行後續處理。在實踐時發現,Activity在onDestroy後,通過WeakReference.get()返回的並不是空。這就是C++與gc的差別。C++中,對象被銷燬後,內存立即釋放,弱引用爲空。但是,Android中,對象被銷燬後,其引用計數爲0,但gc並不一定立即回收,所以此時弱引用仍然有效。

問題解決:

第1步,普通內部類或匿名類放到外部,或改成靜態類。

第2步,存儲弱引用,以便回調時訪問。雖然弱引用不一定異常正確,但還是有必要的,比如內存吃緊時gc直接回收。

第3步,在回調中調用Activity方法時,先判斷isDestroyed(),如果是,那麼可以不必後續處理了。

示例:


public class MyActivity extends AppCompatActivity {
    // 靜態內部類
    private static class MyTask extends AsyncTask<Bundle, Integer, Bundle> {
        // 持有弱引用
        private final WeakReference<MyActivity> weak;
        private MyTask(MyActivity activity) {
            weak = new WeakReference<>(activity);
        }
        protected Bundle doInBackground(Bundle... bundles) {
            Bundle bundle = new Bundle();
            // 耗時操作
            return bundle;
        }
        protected void onPostExecute(Bundle bundle) {
            if (weak.get() == null)
                return;
            weak.get().handleResult(bundle);
        }
    }
    private void doRequest() {
        new MyTask(this).execute();
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章