一,Handler内存泄露的情况:
1,先说handler导致activity内存泄露的原因:
handler发送的消息在当前handler的消息队列中,如果此时activity finish掉了,那么消息队列的消息依旧会由handler进行处理,若此时handler声明为内部类(非静态内部类),我们知道内部类天然持有外部类的实例引用,那么就会导致activity无法回收,进而导致activity泄露。
2,为何handler要定义为static?
因为静态内部类不持有外部类的引用,所以使用静态的handler不会导致activity的泄露
,3,为何handler要定义为static的同时,还要用WeakReference 包裹外部类的对象?
这是因为我们需要使用外部类的成员,可以通过"activity. "获取变量方法等,如果直接使用强引用,显然会导致activity泄露。
演示内存泄露代码:
private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); } }; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_handleroom); findViewById(R.id.btn_send).setOnClickListener(this); tv = findViewById(R.id.tv); // 延时5min发送一个消息,此时handler是持有activity引用的 mHandler.sendEmptyMessageDelayed(1, 5 * 60 * 1000); }
二,我们在开发中应该用到handler更新数据,这是很有可能导致内存泄漏,但我们可以尝试一些弱引用来实现!
1.保证Activity被finish()时该线程的消息队列没有这个Activity的handler内部类的引用。
2.要么让这个handler不持有Activity等外部组件实例,让该Handler成为静态内部类。(静态内部类是不持有外部类的实例的,因而也就调用不了外部的实例方法了)
3.在2方法的基础上,为了能调用外部的实例方法,传递一个外部的弱引用进来)
4.将Handler放到一个单独的顶层类文件中。
1 private MyHandler myHandler; 2 // myHandler = new MyHandler(MainActivity.this); // 实例化 3 private static class MyHandler extends Handler{ 4 private WeakReference<MainActivity> mReference; 5 6 public MyHandler(MainActivity activity){ 7 this.mReference = new WeakReference<>(activity); 8 } 9 @Override 10 public void handleMessage(Message msg) { 11 super.handleMessage(msg); 12 if(mReference != null && mReference.get() != null){ 13 switch (msg.what) { 14 case 1: 15 break; 16 17 } 18 } 19 } 20 }