代码分析:Android中常见Handler内存泄漏

Handler内存泄漏原因

Handler是我们常用的一个对象,在之前的文章已经分析了Handler的工作机制,然而,在使用Handler的过程中容易造成内存泄漏。常见的场景如下。
场景一

public class MainActivity extends AppCompatActivity {
    private CalendarPageView calendar;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                
            }
        },10000);
    }
}

在Java中在内部创建对象之后会隐式的持有外部对象,也就是说new Handler()之后Handler对象对Activity就有了一个持有,那么此时finish掉Activity的话是没办法回收的。这就造成了内存泄漏。
场景二

    private Handler handler = new Handler(){
        @Override
        public void dispatchMessage(Message msg) {
            super.dispatchMessage(msg);
            Activity activity = MainActivity.this;
        }
    };

在里面Handler不仅仅是隐式的持有,也有显示的持有Activity,若执行延时操作也会导致Activity无法被回收。
对于隐式持有,Handler的postDelayed方法,实际上是先把Message添加到MessageQueue中,进而等待Message的执行,所以而Message又是在主线程的Looper中穿件,所以持有链接是ActivityThread->Looper->MessageQueue->Message->Handler->Activity
Handler内存泄漏解决方案
首先Handler的具体实现使用静态内部类的方式。再对外部的Activity进行弱引用。

    static class MyHanler extends Handler{
        WeakReference<Activity> activity;

        public MyHanler(Activity activity) {
            this.activity = new WeakReference<Activity>(activity);
        }

        @Override
        public void dispatchMessage(Message msg) {
            super.dispatchMessage(msg);
            Activity act = activity.get();
            if(null == act){
                return;
            }
        }
    }

然后再创建Handler,由于Activity是弱引用,这样当Activity结束之后Handler无法继续持有Activity,这样避免内存泄漏。
当然若是Handler有延时操作,那么Handler依然会存在,如果延时消息在Activity销毁之后没有存在的必要,那么我们可以在Activity销毁之后删除Handler的消息。

    @Override
    protected void onDestroy() {
        super.onDestroy();
        handler.removeCallbacksAndMessages(null);
    }
    原文作者:iwuyou
    原文地址: https://www.jianshu.com/p/37f4e499346b
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞