赞
踩
在使用各种 listener 时,稍有不注意就会导致内存泄露,因此在使用延时返回的回调时,需要格外小心。
demo
先看一个的 demo:MainActivity 点击按钮后,调用 LongTimeOperation 开启一个耗时 10 秒的线程,并在执行完成后调用回调 onLongTimeCallback()。
MainActivity 中开启耗时操作的代码:
private void startLongTimeOperation() {
LongTimeOperation longTimeOperation = new LongTimeOperation();
LongTimeOperation.LongTimeCallback longTimeCallback = new LongTimeOperation.LongTimeCallback() {
@Override
public void onLongTimeCallback() {
text.setText("onLongTimeCallback");
}
};
longTimeOperation.setLongTimeCallback(longTimeCallback);
longTimeOperation.start();
}
LongTimeOperation 中耗时操作的代码:
public void start() {
new Thread(() -> {
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
mMainHandler.post(() -> {
if (longTimeCallback != null) {
longTimeCallback.onLongTimeCallback();
}
});
}).start();
}
在以上的代码中,由于 longTimeCallback 是匿名内部类,持有了外部的引用,在这个例子里持有了 MainActivity 的引用。
因此,在 MainActivity onDestory() 后,由于 longTimeOperation 持有 longTimeCallback 的引用,而 longTimeCallback 持有了 MainActivity 的引用,导致 GC 的时候无法回收 MainActivity 实例,造成了内存泄露。
改进方案一:将回调中所有对象放入 WeakReference 中
为了避免匿名内部类引用 Activity 的问题,可以把回调里的操作单独提出来,在这个例子中就是回调中需要用到的 TextView。
改动过后,longTimeOperation 引用的是 weakLongTimeCallback,weakLongTimeCallback 中的 TextView 是在 WeakReference 中。因此当 MainActivity 被回收时,textView 也能被回收,避免了内存泄露。
private void startLongTimeOperation() {
L
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。