This Handler class should be static or leaks might occur (null) Handler黄色警告

本文解析了Android中使用Handler时可能引发内存泄漏的原因,并提供了解决方案。通过对比非静态内部类与静态内部类的特性,文章详细介绍了如何通过使用静态Handler类及WeakReference避免内存泄漏。

转 :http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/1106/1922.html

一般我们写Handler的时候会这样写:

这里写图片描述

但是这样我们会被警告:
This Handler class should be static or leaks might occur (null)
意思是:Handler必须是静态的,不然可能会发生内存泄漏

分析:
1.Android App启动的时候,Android Framework 为主线程创建一个Looper对象,这个Looper对象将贯穿这个App的整个生命周期,它实现了一个消息队列(Message Queue),并且开启一个循环来处理Message对象。而Framework的主要事件都包含着内部Message对象,当这些事件被触发的时候,Message对象会被加到消息队列中执行。
2.当一个Handler被实例化时(如上面那样),它将和主线程Looper对象的消息队列相关联,被推到消息队列中的Message对象将持有一个Handler的引用以便于当Looper处理到这个Message的时候,Framework执行Handler的handleMessage(Message)方法。
3.在 Java 语言中,非静态匿名内部类将持有一个对外部类的隐式引用,而静态内部类则不会。

以下面代码为例:

public class SampleActivity extends Activity {

  private final Handler mLeakyHandler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
      // ...
    }
  }

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // Post a message and delay its execution for 10 minutes.
    mLeakyHandler.postDelayed(new Runnable() {
      @Override
      public void run() { }
    }, 60 * 10 * 1000);

    // Go back to the previous Activity.
    finish();
  }
}

当Activity被finish()掉,Message 将存在于消息队列中长达10分钟的时间才会被执行到。这个Message持有一个对Handler的引用,Handler也会持有一个对于外部类(SampleActivity)的隐式引用,这些引用在Message被执行前将一直保持,这样会保证Activity的上下文不被垃圾回收机制回收,同时也会泄露应用程序的资源(views and resources)。

为解决这个问题,下面这段代码中的Handler则是一个静态匿名内部类。静态匿名内部类不会持有一个对外部类的隐式引用,因此Activity将不会被泄露。如果你需要在Handler中调用外部Activity的方法,就让Handler持有一个对Activity的WeakReference,这样就不会泄露Activity的上下文了,正确的写作方式:

public class SampleActivity extends Activity {

  /**
   * Instances of static inner classes do not hold an implicit
   * reference to their outer class.
   */
  private static class MyHandler extends Handler {
    private final WeakReference<SampleActivity> mActivity;

    public MyHandler(SampleActivity activity) {
      mActivity = new WeakReference<SampleActivity>(activity);
    }

    @Override
    public void handleMessage(Message msg) {
      SampleActivity activity = mActivity.get();
      if (activity != null) {
        // ...
      }
    }
  }

  private final MyHandler mHandler = new MyHandler(this);

  /**
   * Instances of anonymous classes do not hold an implicit
   * reference to their outer class when they are "static".
   */
  private static final Runnable sRunnable = new Runnable() {
      @Override
      public void run() { }
  };

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // Post a message and delay its execution for 10 minutes.
    mHandler.postDelayed(sRunnable, 60 * 10 * 1000);

    // Go back to the previous Activity.
    finish();
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值