iis服务器助手广告广告
返回顶部
首页 > 资讯 > 移动开发 >详解Android Handler 机制 (三)内存泄漏
  • 338
分享到

详解Android Handler 机制 (三)内存泄漏

内存泄漏handlerAndroid 2022-06-06 14:06:36 338人浏览 薄情痞子
摘要

ps:看本文之前最好先了解一下Handler源码 常用写法 我们一般使用Handler使用匿名内部类的写法,也就是: private Hand

开篇点题- 。-!.jpeg

ps:看本文之前最好先了解一下Handler源码

常用写法

我们一般使用Handler使用匿名内部类的写法,也就是:

private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        findViewById(R.id.bt_1).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mHandler.sendEmptyMessage(MainActivity.HANDLER_MAIN_CODE);
            }
        });

这时我们就会发现,匿名内部类的地方会报黄:
image.png
*这里提示的大意是:这个Handler类应该被设置为静态否则可能发生内存泄漏。*wtf???为什么会发生内存泄漏。内存泄漏到底是一个什么东西。

内存泄漏是个什么东西

这个嘛,详细内容大家可以阅读《深入理解Java虚拟机》,前段时间刚出第三版,是紫色的,相比第二版加了很多内容。
简单来说就是,当堆中分配的一块内存区域使用完毕,之后不会在被使用到,应该要被回收时,如果还存在一个强引用引用着这块内存区域,那么这块区域就无法被回收。此时就会发生内存泄漏。

使用内部类Handler内存泄漏的原因

那为什么说使用匿名内部类来使用Handler
在handler.sengMessage时,Message拥有了Handler的引用,而内部类Handler隐式的拥有外部类(Activity)的引用。一个线程中有一个Looper,Looper中有唯一一个MessageQueue,而Message在MessageQueue中,也就是产生了下面这条引用链:
Handler引用链

如果此时,Activity销毁,当GC应该回收Activity对象的堆内存区域时,会从Activity实例开始向上检索引用树,如果Message此时还在消息队列中(试着发送一条延迟5min的消息,那么消息会一直在队列中直到5min后这条消息被取出交给Handler处理,在这5min之内Activity被finish掉,但是Activity指向的内存区域是无法回收的,也就是发生了内存泄漏),则这条引用链会一直引用着Activity,使Activity无法销毁,导致内存泄漏。所以,解决方法就要从源头解决,断开引用链:

在Activity的onDestroy回调中调用handler.removeCallbacksAndMessages(断裂上面引用链的第2个箭头)
    @Override
    protected void onDestroy() {
        super.onDestroy();
        mHandler.removeCallbacksAndMessages(null);
    }
使用静态内部类,内部类中使用Activity弱引用(因为收到消息后一般需要用到Context来处理UI或者弹Toast)(断裂上面引用链的第五个箭头)
下面是基于这种方法封装的一个SafeHandler,大家如果能理解下面这个封装的SafeHandler类,那么Android 的Handler内存泄漏知识点就彻底掌握了!:
package com.wiz.car.common.util;
import android.app.Activity;
import android.content.Context;
import android.os.Handler;
import android.util.Log;
import java.lang.ref.WeakReference;

public abstract class SafeHandler extends Handler {
    private final WeakReference mReference;
    private final WeakReference mReferenceT;
    public SafeHandler(Context context, T t) {
        mReference = new WeakReference(context);
        mReferenceT = new WeakReference(t);
    }
    
    public abstract void execute(T t);
    private Runnable innerRun = new Runnable() {
        @Override
        public void run() {
            Context context = mReference.get();
            if(context != null) {
                if(context instanceof Activity && ((Activity)context).isFinishing()){
                    release();
                    LogUtils.w("SafeHandler :","The task executed, but "+context.getClass().getSimpleName()+" is finishing!");
                }else {
                    T t = mReferenceT.get();
                    if(t != null) {
                        execute(t);
                        LogUtils.w("SafeHandler :","The task executed in "+context.getClass().getName());
                    }else{
                        LogUtils.w("SafeHandler :","The task executed, but callback class is null");
                    }
                }
            }else {
                release();
                LogUtils.w("SafeHandler :","The task executed, but activity destroyed!");
            }
        }
    };
    
    public void stop() {
        removeCallbacks(innerRun);
    }
    
    public void release(){
        stop();
        mReference.clear();
        mReferenceT.clear();
    }
    
    public void postDelayed(long time) {
        stop();
        postDelayed(innerRun, time);
    }
}
Zoyp晨 原创文章 3获赞 3访问量 305 关注 私信 展开阅读全文
作者:Zoyp晨


--结束END--

本文标题: 详解Android Handler 机制 (三)内存泄漏

本文链接: https://www.lsjlt.com/news/29788.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作