Handler之内存泄露

Handler之内存泄露

项目相关代码: https://github.com/pyystone/MyAndroidStudyNotes/tree/master/app/src/main/java/pyystone/androidstudynotes/memory/handler

分析

其实在我们开发的时候,图省事,我们会直接写上面那段注释的代码(比如我)

这样的结果其实IDE已经告诉我们了,那就是内存可能会发生泄露,但是往往我们不会去仔细思考和解决办法,也许会很草率得就改成了静态内部类的方式,所以查询了一些资料,在这里进行一些探讨

原因:

当Android应用程序启动时,framework会为该应用程序的主线程创建一个Looper对象。这个Looper对象包含一个简单的消息队列Message Queue,并且能够循环的处理队列中的消息。这些消息包括大多数应用程序framework事件,例如Activity生命周期方法调用、button点击等,这些消息都会被添加到消息队列中并被逐个处理。
另外,主线程的Looper对象会伴随该应用程序的整个生命周期。

然后,当主线程里,实例化一个Handler对象后,它就会自动与主线程Looper的消息队列关联起来。所有发送到消息队列的消息Message都会拥有一个对Handler的引用,所以当Looper来处理消息时,会据此回调[Handler#handleMessage(Message)]

非静态内部类 和 匿名类会持有外部类的的引用,在这里也就是 Activity.this, 当Activity 被finsh回收的时候,这个时候Handler还在引用他,这个时候就会导致Activity 没办法被GC回收。但是静态内部类是不会引用外部类的。

解决方案

  1. 主线程 + 回调

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11

    private Handler mHandler = new Handler(Looper.getMainLooper(), new Handler.Callback() {
    @Override
    public boolean handleMessage(Message msg) {
    if (msg.what == NOTICE_INFO_SYNC) {
    mSyncNoticeView.setVisibility(View.GONE);
    return true;
    }
    return false;
    }
    });
  2. 静态内部类

    1
    2
    3
    4
    5
    6
    static class MyHandler extends Handler {
    @Override
    public void handleMessage(Message msg) {
    // do something
    }
    }
  3. 弱引用 + 静态内部类

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    // WeakReference

    private Handler mHandler = new MyHandler(this);
    private static class MyHandler extends Handler{
    private final WeakReference<Activity> mActivity;
    public MyHandler(Activity activity) {
    mActivity = new WeakReference<Activity>(activity);
    }
    @Override
    public void handleMessage(Message msg) {
    System.out.println(msg);
    if(mActivity.get() == null) {
    return;
    }
    }
    }
  4. weakHandler
    git地址: https://github.com/badoo/android-weak-handler/blob/master/src/main/java/com/badoo/mobile/util/WeakHandler.java

  5. onDestory 的时候销毁掉

    1
    2
    3
    4
    @Override protected void onDestroy() {
    super.onDestroy();
    myHandler.removeCallbacksAndMessages(null);
    }
文章目录
  1. 1. Handler之内存泄露
    1. 1.1. 分析
      1. 1.1.1. 原因:
      2. 1.1.2. 解决方案