在Android开发中使用Handler出现了内存泄漏问题或者HandlerLeak警告
public class MainActivity extends Activity {
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
//...
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
go();
}
private void go(){
Message message = Message.obtain();
mHandler.sendMessage(message);
}
}
@SuppressLint("HandlerLeak")
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
//...
}
};
这种创建Handler的方式会造成内存泄漏,由于mHandler是Handler的非静态匿名内部类的实例,所以它持有外部类Activity的引用,我们知道消息队列是在一个Looper线程中不断轮询处理消息,那么当这个Activity退出时消息队列中还有未处理的消息或者正在处理消息,而消息队列中的Message持有mHandler实例的引用,mHandler又持有Activity的引用,所以导致该Activity的内存资源无法及时回收,引发内存泄漏
避免出现内存泄露的方法:
public class MainActivity extends Activity {
private final Myhandler mHandler = new Myhandler(this);
private static class Myhandler extends Handler{
private WeakReference<MainActivity > mActivity;
public Myhandler(MainActivity activity) {
mActivity = new WeakReference<MainActivity >(activity);
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
MainActivity activity = mActivity.get();
/*
* if (mActivity.get() == null) {
* return;
* }
* //...
*/
if (activity != null) {
//...
}
}
}
创建一个静态Handler内部类,然后对Handler持有的对象使用弱引用,这样在回收时也可以回收Handler持有的对象,这样虽然避免了Activity泄漏,不过Looper线程的消息队列中还是可能会有待处理的消息,所以我们在Activity的Destroy时或者Stop时应该移除消息队列中的消息
@Override
protected void onDestroy() {
super.onDestroy();
mHandler.removeCallbacksAndMessages(null);
}
使用mHandler.removeCallbacksAndMessages(null),是移除消息队列中所有消息和所有的Runnable;当然也可以使用mHandler.removeCallbacks()或mHandler.removeMessages(),来移除指定的Runnable和Message
@Override
protected void onDestroy() {
super.onDestroy();
mHandler.removeMessages(int what);
mHandler.removeCallbacks(Runnable mRunnable);
}