当非静态内部类对象的生命周期比外部类对象的生命周期长时,就会导致内存泄露
我们在正常使用Handler时,mHandler
会作为成员变量保存在发送的消息msg
中,即msg
持有Handler
的引用,而mHandler
是Activity
的非静态内部类实例,即mHandler
持有Activity
的引用,那么msg就相当于
间接持有Activity
的引用。msg
被发送后先放到消息队列MessageQueue
中,然后等待Looper
的轮询处理。那么当Activity
退出后,msg
可能仍然存在于消息对列MessageQueue
中未处理或者正在处理,那么这样就会导致Activity
无法被回收,以致发生Activity
的内存泄露。
解决方法:静态内部类+弱引用的方式。
public class MainActivity extends AppCompatActivity {
private Handler mHandler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mHandler = new MyHandler(this);
init();
}
private void init() {
Message msg = new Message();
msg.what = 0;
mHandler.sendMessage(msg);
}
private static class MyHandler extends Handler {
private WeakReference<MainActivity> activityWeakReference;
public MyHandler(MainActivity activity) {
activityWeakReference = new WeakReference<>(activity);
}
@Override
public void handleMessage(Message msg) {
MainActivity activity = activityWeakReference.get();
if (activity != null) {
switch(msg.what) {case 0:break;default:break
}
}
}
}
}
通过mHandler使用
弱引用持有Activity
,当GC执行垃圾回收时,遇到Activity
就会回收并释放所占据的内存单元。这样就不会发生内存泄露了。
但是发送的msg
不再持有Activity
的引用,但是msg
还是有可能存在消息队列MessageQueue
中,所以同时重写onDestroy方法,把mHandler
的回调和发送的消息给移除掉。
@Override
protected void onDestroy() {
super.onDestroy();
mHandler.removeCallbacksAndMessages(null);
}
ps:WeakReference<T>:弱引用-->随时可能会被垃圾回收器回收,不一定要等到虚拟机内存不足时才强制回收