一、Handler造成内存泄露的原因
在Activity中,将Handler声明成非静态内部类或匿名内部类,这样Handle默认持有外部类Activity的引用。如果Activity在销毁时,Handler还有未执行完或者正在执行的Message,而Handler又持有Activity的引用,导致GC无法回收Activity,导致内存泄漏。如以下两种情形可能导致内存泄漏
1、在Activity内将Handler声明成匿名内部类
//匿名内部类 private Handler mHandler = new Handler() { @Override public void handleMessage(@NonNull Message msg) { super.handleMessage(msg); } };
new Handler().postDelayed(new Runnable() { @Override public void run() { //大量的操作,activity要销毁时还没结束 } },1000);
2、在Activity内将Handler声明成非静态内部类:
//非静态内部类 private class MyHandler extends Handler{ @Override public void handleMessage(@NonNull Message msg) { super.handleMessage(msg); } } private MyHandler mHandler = new MyHandler();
二、解决方案
1、静态内部类 + 弱引用
private static class MyHandler extends Handler { //弱引用,在垃圾回收时,activity可被回收 private WeakReference<MainActivity> mWeakReference; public MyHandler(MainActivity activity) { mWeakReference = new WeakReference<>(activity); } @Override public void handleMessage(@NonNull Message msg) { super.handleMessage(msg); } }
2.在Activity销毁时,清空Handler中未执行或正在执行的Callback以及Message:
@Override protected void onDestroy() { super.onDestroy(); //清空handler管道和队列 mHandler.removeCallbacksAndMessages(null); }
3:非静态内部类 + 弱引用,在activity要回收时清除引用(麻烦,不推荐)
private class MyHandler extends Handler { //弱引用,在垃圾回收时,activity可被回收 private WeakReference<MainActivity> mWeakReference; public MyHandler() { this.mWeakReference = new WeakReference<>(MainActivity.this); } @Override public void handleMessage(@NonNull Message msg) { super.handleMessage(msg); } } private MyHandler mHandler = new MyHandler(); @Override protected void onDestroy() { super.onDestroy(); //手动清除应用 mHandler.mWeakReference.clear(); }