Android代码优化之Handler内存泄漏

目录

目录

前言

Android代码中涉及进程间通信的地方经常会使用Handler。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class MainActivity extends AppCompatActivity {
//可能引入内存泄漏的方法
private Handler handler=new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}

而上面这种用法可能会导致内存泄漏,比如使用如下代码,由于消息会在5分钟后发送,所以当用户进入并退出Activity后,在消息发送并处理完成之前,这个Activity是不会被回收的,这样就会导致内存泄漏。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class MainActivity extends AppCompatActivity {
//可能引入内存泄漏的方法
private Handler handler=new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//5分钟后发送消息
handler.postDelayed(new Runnable() {
@Override
public void run() {
Log.e("测试","123");
}
},1000*10*5);
}
}

内存泄漏的原因

由于Handler、Looper和MessageQueue是一起工作的,在Android中一个应用启动后系统会默认创建一个用于处理主线程所有Message对象的Looper对象,它的生命周期贯穿于整个应用的生命周期,所以在主线程使用Handler的时候都会默认绑定这个Looper对象并关联MessageQueue,这时发送到MessageQueue的Message对象都会持有这个Handler对象的引用,这样Looper在处理消息的时候才能回调到Handler中年的handleMessage方法。因此如果Message对象还没有处理完成,那么Handler对象也就不会被垃圾回收。而在Java中非静态内部类会持有外部类的一个隐式引用,所以当Handler无法回收时由于Handler持有MainActivity的引用导致MainActivity也无法被回收,从而导致内存泄漏。

解决方法:将Handler改为静态内部类并使用弱引用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public class MainActivity extends AppCompatActivity {
private final InnerHandler mInnerHandler=new InnerHandler(this);
private final Runnable sRunnable=new Runnable() {
@Override
public void run() {
Toast.makeText(MainActivity.this, "解决方法", Toast.LENGTH_SHORT).show();
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mInnerHandler.postDelayed(sRunnable,1000*60*5);
}
private static class InnerHandler extends Handler{
private final WeakReference<MainActivity> activityWeakReference;

public InnerHandler(MainActivity activity) {
this.activityWeakReference = new WeakReference<MainActivity>(activity);
}

@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
MainActivity activity=activityWeakReference.get();
if(activity!=null){

}
}
}
}
坚持原创技术分享,您的支持将鼓励我继续创作!
-------------本文结束感谢您的阅读-------------