内部Handler类引起的泄露

如果在Activity中定义了一个内部Handler类,会出现一个内存泄露警告:
This Handler class should be static or leaks might occur…
In Android, Handler classes should be static or leaks might occur. Messages enqueued on the application thread’s MessageQueue also retain their target Handler. If the Handler is an inner class, its outer class will be retained as well. To avoid leaking the outer class, declare the Handler as a static nested class with a WeakReference to its outer class.

private Handler mHandler = new Handler() {
     public void handleMessage(Message msg) {
     }
}
public void onCreate(Bundle savedInstanceState) {
     ……
     mHandler.sendMessageDelayed(Message.obtain(), 60000);
     finish();
}


原因是:
  1. 当Android应用启动的时候,会先创建一个应用主线程的Looper对象,Looper实现了一个简单的消息队列,一个一个的处理里面的Message对象。主线程Looper对象在整个应用生命周期中存在。

  2. 当在主线程中初始化Handler时,该Handler和Looper的消息队列关联。发送到消息队列的Message会引用发送该消息的Handler对象,这样系统可以调用 Handler#handleMessage(Message) 来分发处理该消息。

  3. 在Java中,非静态(匿名)内部类会引用外部类对象。而静态内部类不会引用外部类对象。

  4. 如果外部类是Activity,则Activity会一直被Handler引用,而无法释放,造成内存泄露 。

各个对象的引用关系:
MainThread -> Looper -> MessageQueue -> Message -> Handler -> Activity
主线程在整个应用的生命周期中,是一直存在的,所以如果Message一直在MessageQueue中存在的话(如延迟发送消息等),则Handler对象会一直被引用,而如果Handler是非静态内部类,则其会一直引用Activity。

最佳方式,采用WeakReference:

static class MyHandler extends Handler {
     WeakReference<Activity> mWeakReferenceActivity;
     public MyHandler(SplashActivity activity) {
          mWeakReferenceActivity = new WeakReference<Activity>(activity);
     }
     @Override
     public void handleMessage(Message msg) {
          super.handleMessage(msg);
          SplashActivity activity = mWeakReferenceActivity.get();
          if(activity == null) {
               return;
          }
     }
}

private MyHandler mMyHandler = new MyHandler(this);






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值