首页 > 技术文章 > Handler 内存泄漏处理方法

finn21 2019-12-05 09:34 原文

一,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     }

推荐阅读