Handler之内存泄露
分析
其实在我们开发的时候,图省事,我们会直接写上面那段注释的代码(比如我)
这样的结果其实IDE已经告诉我们了,那就是内存可能会发生泄露,但是往往我们不会去仔细思考和解决办法,也许会很草率得就改成了静态内部类的方式,所以查询了一些资料,在这里进行一些探讨
原因:
当Android应用程序启动时,framework会为该应用程序的主线程创建一个Looper对象。这个Looper对象包含一个简单的消息队列Message Queue,并且能够循环的处理队列中的消息。这些消息包括大多数应用程序framework事件,例如Activity生命周期方法调用、button点击等,这些消息都会被添加到消息队列中并被逐个处理。
另外,主线程的Looper对象会伴随该应用程序的整个生命周期。然后,当主线程里,实例化一个Handler对象后,它就会自动与主线程Looper的消息队列关联起来。所有发送到消息队列的消息Message都会拥有一个对Handler的引用,所以当Looper来处理消息时,会据此回调[Handler#handleMessage(Message)]
非静态内部类 和 匿名类会持有外部类的的引用,在这里也就是 Activity.this, 当Activity 被finsh回收的时候,这个时候Handler还在引用他,这个时候就会导致Activity 没办法被GC回收。但是静态内部类是不会引用外部类的。
解决方案
主线程 + 回调
1
2
3
4
5
6
7
8
9
10
11
private Handler mHandler = new Handler(Looper.getMainLooper(), new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
if (msg.what == NOTICE_INFO_SYNC) {
mSyncNoticeView.setVisibility(View.GONE);
return true;
}
return false;
}
});静态内部类
1
2
3
4
5
6static class MyHandler extends Handler {
@Override
public void handleMessage(Message msg) {
// do something
}
}弱引用 + 静态内部类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16// WeakReference
private Handler mHandler = new MyHandler(this);
private static class MyHandler extends Handler{
private final WeakReference<Activity> mActivity;
public MyHandler(Activity activity) {
mActivity = new WeakReference<Activity>(activity);
}
@Override
public void handleMessage(Message msg) {
System.out.println(msg);
if(mActivity.get() == null) {
return;
}
}
}weakHandler
git地址: https://github.com/badoo/android-weak-handler/blob/master/src/main/java/com/badoo/mobile/util/WeakHandler.javaonDestory 的时候销毁掉
1
2
3
4@Override protected void onDestroy() {
super.onDestroy();
myHandler.removeCallbacksAndMessages(null);
}