Android App 内存泄露之Handler

本文探讨了在Android应用开发中,Handler与Activity生命周期不一致导致的内存泄漏问题,详细解释了其原理,并提供了避免内存泄漏的解决方案。

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

一.概述

Handler是我们开发中经常用到的一个类,其实Handler是造成内存泄漏的一个重要源头,主要就是因为和Activity的生命周期不一致导致的,Hanlder引用Activity会造成内存泄漏。

看一下如下代码

这里写图片描述

开发工具提示我们,这个Hanlder类应该声明为静态的,否则可能发生内存泄漏。
为什么会出现这样的问题?

Handler的生命周期和Activity不一致

  • 当Android应用启动的时候,会先创建一个UI主线程的Looper对象,Looper实现了一个简单的消息队列,一个一个的处理里面的Message对象。主线程Looper对象在整个应用生命周期中存在。
  • 当在主线程中初始化Handler时,该Handler和Looper的消息队列关联(没有关联会报错的)。发送到消息队列的Message会引用发送该消息的Handler对象,这样系统可以调用 Handler#handleMessage(Message) 来分发处理该消息。

    Handler引用Activity阻止了GC对Activity的回收

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

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

如何避免
1.使用静态内部类
2.使用弱引用

代码如下:

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //创建Handler实例的时候把外部类的对象传进去
        MyHandler handler = new MyHandler(this);
        handler.sendEmptyMessageDelayed(0,200);
    }
    //将Handler类声明为静态内部类
    public static class MyHandler extends Handler{
        public WeakReference<MainActivity> mActivity ;
        public MyHandler(MainActivity activity){
            //使用弱引用,保存外部类Activity的对象
            mActivity = new WeakReference<MainActivity>(activity);
        }
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            if(mActivity.get()==null){
                return;
            }
            //调用Activity中的方法
            mActivity.get().todo();
        }
    }
    public void todo(){
        Toast.makeText(this, "hello", Toast.LENGTH_SHORT).show();
    }
}

上面这样就可以了吗?

当Activity finish的时候,消息对象还是在消息队列中排队,还是会处理消息,这是没必要的,所以最好的方法是在Activity onStop或者onDestory的时候取消掉该Handler对象的Message和Runnable。

@Override
    protected void onDestroy() {
        handler.removeCallbacksAndMessages(null);
        super.onDestroy();
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值