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();
    }
}

 

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