Android内存泄漏之 handler

本文深入探讨了Android应用中Handler对象如何引发内存泄漏的问题,并提供了两种解决策略:一种是在Activity的onDestroy方法中解绑Handler,另一种是通过静态改造Handler断开与外部类的联系。此外,文章还介绍了如何利用MyHandler类和WeakReference来避免内存泄露,确保资源的合理回收。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Handler是我们经常使用的一个工具,如果细心的同学会发现,当我们在声明一个handler对象时,android lint往往会提示一个可能导致内存泄漏的警告,如下图:
这里写图片描述

那么Handler到底是如何导致内存泄漏的呢?

当Android程序第一次创建的时候,在主线程同时会创建一个Looper对象。Looper实现了一个简单的消息队列,一个接着一个处理Message对象。程序框架所有主要的事件(例如:屏幕上的点击时间,Activity生命周期的方法等等)都包含在Message对象中,然后添加到Looper的消息队列中,一个一个处理。主线程的Looper存在整个应用程序的生命周期内。
当一个Handler对象在主线程中创建的时候,它会关联到Looper的 message queue 。Message添加到消息队列中的时候Message会持有当前Handler引用,当Looper处理到当前消息的时候,会调用Handler#handleMessage(Message).
在java中,no-static的内部类会 隐式的 持有当前类的一个引用。static的类则没有。
当Activity结束后,在 Message queue 处理这个Message之前,它会持续存活着。这个Message持有Handler的引用,而Handler有持有Activity的引用,这个Activity所有的资源,在这个消息处理之前都不能也不会被回收,所以发生了内存泄露。

看一段导致内存泄漏的代码,可以结合LeakCanary工具跟踪内存泄漏信息

public class SampleActivity extends Activity { 

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

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

    // 发送一个10分钟后执行的一个消息 
    mHandler.postDelayed(new Runnable() { 
      @Override 
      public void run() { } 
    }, 600000); 

    // 结束当前的Activity 
    finish(); 
  } 
} 

知道原理后,那么该如何解决呢?

方法有两种,第一种是从代码逻辑上,我们在activity onDestroy方法中,对handler进行解绑;(不推荐,面向过程)
另一种,就是直接将handler进行静态改造,断开Handler 和外部class的联系。(推荐)

然而声明了handler为静态时,问题来了,静态类使用的方法也需要静态,难道我要在Activity中通过申明大量的static 变量提供给handler 使用???
这里写图片描述
这样的代码不仅难看而且设计很不合理,所以我们的方法如下因为你在MyHandler 有一个mActivity的弱引用,然后可以调用mActivity的任何public 函数和变量。所以,你只需要 在mAcivity 中定义 public XXX getXXX()方法把你需要提供给MyHandler 的变量封装起来,就可以啦。

  static class MyHandler extends Handler {

        WeakReference mActivity;



        MyHandler(PopupActivity activity) {

            mActivity = new WeakReference(activity);

        }



        @Override

        public void handleMessage(Message msg) {

            PopupActivity theActivity = mActivity.get();

            switch (msg.what) {

                case 0:

                    theActivity.popPlay.setChecked(true);

                    break;

            }

        }

    };
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值