Handler引起的内存泄露(Activity中Handler的正确使用方法)

转载 2015年02月04日 17:15:54

如果你在Activity中定义了一个内部Handler类,如下代码:

public class MainActivity extends Activity {
 
    private  Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            //TODO handle message...
        }
    };
 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mHandler.sendMessageDelayed(Message.obtain(), 60000);
 
        //just finish this activity
        finish();
    }
}

然后运行Android Lint工具会有一个内存泄露警告:

This Handler class should be static or leaks might occur (com.example.ta.MainActivity.1)
Issue: Ensures that Handler classes do not hold on to a reference to an outer class
Id: HandlerLeak
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.

原因是:

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

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

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

  • 如果外部类是Activity,则会引起Activity泄露 。

当Activity finish后,延时消息会继续存在主线程消息队列中1分钟,然后处理消息。而该消息引用了Activity的Handler对象,然后这个Handler又引用了这个Activity。这些引用对象会保持到该消息被处理完,这样就导致该Activity对象无法被回收,从而导致了上面说的 Activity泄露。

要修改该问题,只需要按照Lint提示的那样,把Handler类定义为静态即可,然后通过WeakReference 来保持外部的Activity对象。

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;
        }
    }
}

所以,当你在Activity中使用内部类的时候,需要时刻考虑您是否可以控制该内部类的生命周期,如果不可以,则最好定义为静态内部类。

参考文章: http://blog.chengyunfeng.com/?p=468

Handler最正确的写法(避免内存泄露)

/**                         Handler最正确的写法:  handler重点在  原理  和 内存泄露  *   *   * Handler的内存泄露问题:  * 目的:...
  • u014074418
  • u014074418
  • 2015年09月14日 23:12
  • 4515

Handler内存泄漏详解及其解决方案

在android开发过程中,我们可能会遇到过令人奔溃的OOM异常,面对这样的异常我们是既熟悉又深恶痛绝的,因为造成OOM的原因有很多种情况,如加载图片过大,某已不再使用的类未被GC及时回收等等.......
  • javazejian
  • javazejian
  • 2016年03月09日 22:28
  • 6476

安卓性能优化之清除Handler的Message和Runnable

Handler是由系统所提供的一种异步消息处理的常用方式,一般情况下不会发生内存泄露. 但既然是调优,当在A_Activity中使用handler发送了几个消息,然后又跳到B_Activity,这个时...
  • stzy00
  • stzy00
  • 2015年02月28日 17:56
  • 9896

Handler退出,线程退出

looper退出 当我们调用Looper的quit方法时,实际上执行了MessageQueue中的removeAllMessagesLocked方法,该方法的作用是把MessageQueue消息池中...
  • qq_30196607
  • qq_30196607
  • 2016年05月17日 15:46
  • 2239

Handler造成Activity泄漏,用弱引用真的有用么?

网上很多教程,解决Handler造成的内存泄漏问题,基本上是使用弱引用来解决的,但是使用弱引用真的有效么?直接写代码演示,以及分析。 下面分析过程分为4种,第一种是Handler声明成静态的并且弱引用...
  • u013356254
  • u013356254
  • 2016年09月07日 21:45
  • 5024

Android Handler正确使用姿势

Android Handler正确使用姿势
  • geanwen
  • geanwen
  • 2017年01月08日 15:14
  • 1564

Handler的正确写法

Handler我们常常用于通知主线程做相对应的操作,但是如果使用不但的话就会造成内存泄露,所以记录写正确的Handler写法。Handler handler = new Handler() { ...
  • Neacy_Zz
  • Neacy_Zz
  • 2015年05月19日 21:42
  • 2421

Handler常见用法小结

这次对Hanlder的常见用法做一个小结,巩固一下基础知识。在Handler的异步操作中,我们会使用到Handler,Message,Looper。 Handler一般用来接收Message...
  • TobeStrong_csdn
  • TobeStrong_csdn
  • 2016年09月05日 17:24
  • 2814

Handler的基本用法和原理简介

介绍      在平时的安卓开发过程中,Handler一定不少见,Handler是Android消息机制的上层接口,这使得在开发过程中只需要和Handler交互即可。很多人认为Handler的作用就是...
  • bingozhang24
  • bingozhang24
  • 2016年07月21日 19:58
  • 2052

Android中Handler的使用

Handler是Android中引入的一种让开发者参与处理线程中消息循环的机制。每个Hanlder都关联了一个线程,每个线程内部都维护了一个消息队列MessageQueue,这样Handler实际上也...
  • sunqunsunqun
  • sunqunsunqun
  • 2015年07月29日 00:16
  • 36583
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Handler引起的内存泄露(Activity中Handler的正确使用方法)
举报原因:
原因补充:

(最多只允许输入30个字)