问题描述:
使用普通内部类或匿名类开启线程执行耗时任务,若任务没有结束而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();
}
}