Android开发:详解Handler的内存泄露

python爬虫抖音 个人资料 仅供学习参考 切勿用于商业 本文仅供学习参考 切勿用于商业 本次爬取使用fiddler+模拟器(下载抖音APP)+pycharm 1. 下载最新版本的fiddler(自行百度下载),以及相关配置 1.1.依次点击,菜单栏-Tools-Options-HTTPS,如图1红框打钩,HTTPS旁边Connections配置,如图2红框打钩 1.2.再次点击HTTPS栏,点击Actions选择第二个…to ... 阅读详情

前言

  • 内存泄露在Android开发中非常常见

    1. 内存泄露的定义:本该被回收的对象不能被回收而停留在堆内存中
    2. 内存泄露出现的原因:当一个对象已经不再被使用时,本该被回收但却因为有另外一个正在使用的对象持有它的引用从而导致它不能被回收。
      这就导致了内存泄漏。
  • 本文将详细讲解内存泄露的其中一种情况:在Handler中发生的内存泄露

    阅读本文前建议先阅读Android开发:Handler异步通信机制全面解析(包含Looper、Message Queue)


目录


目录

1. 背景

我们先来看下日常Handler的一般用法:

public class MainActivity extends AppCompatActivity {


    @Override
    protected void onCreate(Bundle savedInstanceState) {
    //主线程创建时便自动创建Looper和对应的MessageQueue,之前执行Loop()进入消息循环
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

    //实例化Handler
    //这里并无指定Looper,即自动绑定当前线程(主线程)的Looper和MessageQueue
        private Handler showhandler = new Handler(){
        //通过复写handlerMessage()从而决定如何进行更新UI操作
        @Override
        public void handleMessage(Message msg) {
        //UI更新操作
            }
    };
    //启动子线程
        new Thread(){
            @Override
            public void run() {
                super.run();
                try {
                    Thread.sleep(10000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                 showhandler.sendEmptyMessageDelayed(0x1,10000);

                }
            }
        }.start();

      finish();
}

在上面的例子中,你会发现出现了严重的警告:


Paste_Image.png

从上图可以看出来,这个警告的原因是:该Handler造成了严重的内存泄漏

那么,该Handler是怎么样造成内存泄露的呢?

2. 内存泄露原因

2.1 造成内存泄露的源头

根据图片可以分析,内存泄露显示出现在:

  • Handler类

    即Handler四件套:Looper+MessageQueue+Message+Handler

  • 最终的泄露发生在Handler类的外部类 - MainActivity类
2.2 如何造成内存泄露

首先,我们需要了解到:

  • 主线程的Looper对象会伴随该应用程序的整个生命周期
  • 在Java里,非静态内部类匿名类都会潜在引用它们所属的外部类

在了解到上述两条后,从上面的代码中可以知道:

  • 在发送的延迟空消息(EmptyMessageDelayed)后、消息处理被前,该消息会一直保存在主线程的消息队列里持续10s
  • 在这延时10s内,该消息内部持有对handler的引用,由于handler属于非静态内部类,所以又持有对其外部类(即MainActivity实例)的潜在引用,引用关系如下图

引用关系
  • 这条引用关系会一直保持直到消息得到处理,从而,这阻止了MainActivity被垃圾回收器(GC)回收,同时造成应用程序的内存泄漏,如下图:

    泄露分析

3. 解决方案

3.1 解决方案1:使用静态内部类+弱引用

上面提到,在Java里,非静态内部类匿名类都会潜在的引用它们所属的外部类。
但是,静态内部类不会。

所以,避免内存泄露的解决方案是:只需要将Handler的子类设置成静态内部类

  • 同时,还可以加上 使用WeakReference弱引用持有Activity实例
  • 原因:弱引用的对象拥有短暂的生命周期。在垃圾回收器线程扫描时,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。

解决代码如下:

public class MainActivity extends AppCompatActivity {


//将Handler改成静态内部类
     private static class FHandler extends Handler{
      //定义弱引用实例
      private WeakReference<Activity> reference; 

      //在构造方法中传入需要持有的Activity实例
      public MyHandler(Activity activity) { 
      reference = new WeakReference<Activity>(activity); }

        //通过复写handlerMessage()从而决定如何进行更新UI操作
        @Override
        public void handleMessage(Message msg) {
        //省略代码
            }
}

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    //主线程创建时便自动创建Looper和对应的MessageQueue,之前执行Loop()进入消息循环
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

    //实例化Handler的子类
    //这里并无指定Looper,即自动绑定当前线程(主线程)的Looper和MessageQueue
        private final Handler showhandler = new FHandler();

         //启动子线程
        new Thread(){
            @Override
            public void run() {
                super.run();
                try {
                    Thread.sleep(10000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                 showhandler.sendEmptyMessageDelayed(0x1,10000);

                }
            }
        }.start();
    }
3.2 解决方案2:当外部类结束生命周期时清空消息队列
  • 从上面分析,内存泄露的原因是:
    当Activity结束生命周期时,Handler里的Message可能还没处理完,从而导致一系列的引用关系。
  • 其实,我们只要在当Activity结束生命周期时清除掉消息队列(MessageQueue)里的所有Message,那么这一系列引用关系就不会存在,就能防止内存泄露。
  • 解决方案:当Activity结束生命周期时(调用onDestroy()方法),同时清除消息队列里的所有回调消息(调用removeCallbacksAndMessages(null))

代码如下:

@Override
    protected void onDestroy() {
        super.onDestroy();
        mHandler.removeCallbacksAndMessages(null);
    }

经过上述两个解决方案,在Handler里的内存泄露问题就不会再出现了!


4. 总结

  • 本文总结的是关于Handler的一些小事:内存泄露,阅读完本文后相信你已经懂得Handler内存泄露的原理和详细的解决方案
  • 接下来,我会继续讲解Android开发中关于Handler和多线程的知识,包括Handler源码、继承Thread类、实现Runnable接口、Handler等等,有兴趣可以继续关注Carson_Ho的安卓开发笔记
MAX30102心率血氧传感器 估算AC、DC值的方法如下:找两个波谷点,两个波谷点之间有一个波峰点,两个波谷点相连成一条直线,与Y轴平行的线穿过波峰点会与两个波谷点连接成的直线相交于一点,这个点就是DC点,DC点的Y轴对应值就是直流分量,AC分量的值为波峰点到DC点之间的差值。在医院测量中常用的一种血氧采集方式,如下图所示,光电传感器和光源分别置于手指的两侧,光源穿过手指被另一侧的光电二极管接收,根据光衰减量计算血氧浓度。那么,根据上面的Beer-Lambert 定理,针对测量的具体场景,测量过程的衰减为三层穿透物质衰减量的叠加。 阅读详情

相关推荐

CloudCompare&PCL 体元累加法(树冠体积计算)

文章目录

dayuhaitang1的博客 1509

handler内存泄漏情景分析

目录 前言 一、handler的几种创建方式 二、何时产生内存泄漏? 三、再谈handler内存泄漏 前言 一直以来,无论是在工作还是面试中,关于内存泄漏的话题,肯定是绕不开的。其中最典型的就是handler的内存泄漏问题,今天就带着大家一起探究一下handler内存泄漏的真正原因和场景。 一、handler的几种创建方式 先上图: 相信大家在平时开发过程中定义handler时,最常见就是以上这三种了。 第一种:直接使用匿名内部类 第二种:内部类方式 第三种:静态内部类.

baochengchen的博客 382

使用R语言整理GEO数据的简易教程

本教程介绍了使用R语言从GEO数据库下载数据并进行数据整理的基本步骤。根据实际研究问题,你可能需要进行更复杂的数据处理和分析。R语言作为一种强大的生物信息学工具,为GEO数据的整理、分析和可视化提供了丰富的功能和工具。希望这个教程能够帮助你入门GEO数据整理和R语言的应用。如果你在使用过程中遇到问题,或需要进一步的指导,请随时向我询问。祝你在GEO数据分析的旅程中取得成功!

Mrrunsen的博客 3704

Android Handler sendEmptyMessageDelayed 和 sendEmptyMessage 的使用

sendEmptyMessageDelayed 一般我们做延时操作的时候使用到 比如现在有一个延时10跳转的demo 如下 public class MainActivity extends AppCompatActivity implements Handler.Callback { private Handler handler; @Override pr...

小牧在一直在学习,在前进的道路上大家一起学习,进步。 2万+

重谈Handler的内存泄漏

handler有没有处理的消息或者正在处理消息,此时Handler的生命周期明显比Activity长,GC持有Activity与handler两者的引用,导致Activity无法被GC回收,造成内存泄漏。而handler是不是内部类,并不是造成内存泄漏的根本原因。

huahaiyi的博客 305

Android使用Handler造成内存泄露的分析及解决方法

为了防止Handler内存泄漏有哪些手段?如何预防Handler内存泄漏?

weixin_38090079的博客 1152

了解 Android 内存泄露

一、说明 看文章之前,可以预想一下,你想从这篇文章中了解什么呢? 什么是内存泄露 内存泄露有什么危害 怎样检测内存泄露 怎样解决内存泄露 本文主要想说明什么是内存泄露、怎样检测和解决内存泄露。 希望大家在看完该文后能对内存泄露有一个全面的了解。 二、什么是内存泄露 内存泄漏是指程序已经不会再使用的内存对象,由于垃圾回收时无法识别其是否为无用的垃圾对象,不能及时地将其回收,一直保留在内存中占用存储空间,不释放给其他对象。 举个例子: 茅坑只有那么那么五六个,但有些总喜欢占着茅坑不拉屎,这样就

Eric的博客 1167

Android App 内存泄露Handler

Android App 内存泄露Handler, 你可能忽略的东东

The Tech-Dragon 3万+

Android 解决handler内存泄露的方法

文章目录1、简介2、方法一避免Handler 泄露3、方法二添加弱连接 1、简介 大体理解为: Handler 在使用的时候一般要依附于一个对象,很多时候 handler 延时发送的时候 ,所依附的对象得不到释放,于是出现了 handler 泄露。 2、方法一避免Handler 泄露 1)在对象被销毁的时候 断掉与Handler 的联系,销毁Handler 消息的处理。 @Override pub...

Venus 的博客 5202

Android 内存泄露详解 Handler 内存泄露的原因

前言 在Android开发中,内存泄露 十分常见 1.内存泄露的定义:本该被回收的对象不能被回收而停留在堆内存中 2.内存泄露出现的原因:当一个对象已经不再被使用时,本该被回收但却因为有另外一个正在使用的对象持有它的引用从而导致它不能被回收。 这就导致了内存泄漏。 本文将详细讲解内存泄露的其中一种情况:在Handler中发生的内存泄露 1. 问题描述 Handler的一般用法 = 新建...

Android 开发架构 1001

Android Handler内存泄露场景分析

在前面一篇博客《Android全面解析Handler》一文中,我们认识了Handler的异步通信机制,同时也提到过Handler如果使用不慎将会导致内存泄露。今天主要来讲述一下Handler内存泄露场景可能存在的场景以及解决方案。 场景一:直接传递外部类引用到静态内部类使用,导致静态内部类间接持有外部类的引用 举个栗子,在一个静态内部类我们想访问外部类的成员属性,怎么办?可不可以直接访问了,答案当然是不想的,如下所示,我们的代码提示是会直接报错的: public class TestActivity ex

hirezy 7958

关于Android中使用Handler造成内存泄露的分析和解决

如下图所示:编译器便已提示:该程序类应该是静态的且可能会发生泄漏上面是一段简单的Handler的使用。当使用内部类(包括匿名类)来创建Handler的时候,Handler对象会隐式地持有一个外部类对象(通常是一个Activity)的引用(不然你怎么可能通过Handler来操作Activity中的View?)。而Handler通常会伴随着一个耗时的后台线程(例如从网络拉取图片)一起出现,这个后台线程在任务执行完毕(例如图片下载完毕)之后,通过消息机制通知Handler,然后Handler把图片更新到界面。然而

2401_84150043的博客 909

androidhandler内存泄漏解决方法,Android 内存泄露详解 Handler 内存泄露的原因与解决方案...

前言在Android开发中,内存泄露 十分常见1.内存泄露的定义:本该被回收的对象不能被回收而停留在堆内存中2.内存泄露出现的原因:当一个对象已经不再被使用时,本该被回收但却因为有另外一个正在使用的对象持有它的引用从而导致它不能被回收。这就导致了内存泄漏。本文将详细讲解内存泄露的其中一种情况:在Handler中发生的内存泄露目录1.png1. 问题描述Handler的一般用法 = 新建Handle...

weixin_30249997的博客 619

AndroidHandler造成内存泄露分析

Java使用有向图机制,通过GC自动检查内存中的对象(什么时候检查由虚拟机决定),如果GC发现一个或一组对象为不可到达状态,则将该对象从内存中回收。也就是说,一个对象不被任何引用所指向,则该对象会在被GC发现的时候被回收;另外,如果一组对象中只包含互相的引用,而没有来自它们外部的引用(例如有两个对象A和B互相持有引用,但没有任何外部对象持有指向A或B的引用),这仍然属于不可到达,同样会被GC回收。 Android中使用Handler造成内存泄露的原因 Handler mHandler = new Handl

sinat_36955332的博客 178

android Handler导致的内存泄露的原因及解决办法

Android开发中,内存泄露十分常见。 内存泄露:本该被回收的对象不能被回收而停留在堆内存中占用内存。这样最后可能会引起内存不足导致其他需要使用内存的对象无法获取足够的内存,进而引起内存溢出OOM。 内存泄露出现的原因:当一个对象已经不再被使用时,本该被回收但却因为有另外一个正在使用的对象持有它的引用从而导致它不能被回收。这就导致了内存泄漏。 Handler是我们在更新UI时经常使用到的类,但...

HelloWorld的专栏 1177

关于安卓Handler内存泄漏及解决方案

Handler是安卓中常见的实现异步操作的方法,使用简单,但是操作不注意很容易造成内存泄漏。

怎么可以吃恐龙呢 1770

Android ---【内存优化】Handler 内存泄漏原因及解决方案

Handler造成内存泄露的原因。非静态内部类,或者匿名内部类。使得Handler默认持有外部类的引用。在Activity销毁时,由于Handler可能有未执行完/正在执行的Message。导致Handler持有Activity的引用。进而导致GC无法回收Activity。匿名内部类: 非静态内部类: 三、解决方法 静态内部类+弱引用 Activity销毁时,清空Handler中,未执行或正在执行的Callback以及Message。 四、内部类为什么会持有外部类的引用 这是因为内部类虽然和外部类写在同一个

梁同学与Android 8248

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

android开发过程中,我们可能会遇到过令人奔溃的OOM异常,面对这样的异常我们是既熟悉又深恶痛绝的,因为造成OOM的原因有很多种情况,如加载图片过大,某已不再使用的类未被GC及时回收等等......本篇我们就来分析其中一种造成OOM的场景,它就是罪恶的内存泄漏。对于这样的称呼,我们并不陌生,甚至屡次与之"并肩作战",只不过它就是一个猪队友,只会不断送塔....... 本篇分为3部分:

zejian的博客 4万+

android 内存泄露分析心得,安卓开发-Handler内存泄漏分析及解决

一、介绍首先,请浏览下面这段handler代码:publicclassSampleActivityextendsActivity{privatefinalHandlermLeakyHandler=newHandler(){@OverridepublicvoidhandleMessage(Messagemsg){//...}}}在使用hand...

weixin_35655990的博客 222

解决Handler导致的内存泄漏真实样例

背景最近自己项目上用了网上的AutoScrollViewPager 开源Viewpager。没怎么关注别人开源的项目一些代码质量问题, 因为潜意识上别人开源在网上的肯定是令人满意的代码。最近意识到了这种心态其实并不好,而且不利于自身技术的提升。样例贴这个View的内存泄漏的样例,是因为发现很多程序员们在使用一些第三方开源框架,特别是一些自定义view的特效时,会用到一些延时任务之类的,那就会用到Ha

Marshon的专栏 2068

androidhandler内存泄漏解决方法,Handler内存泄漏原因及解决方案

Handler内存泄漏原因及解决方案目录:1.须知:主线程Looper生命周期和Activity的生命周期一致。非静态内部类,或者匿名内部类。默认持有外部类引用。2.原因:Handler造成内存泄露的原因。非静态内部类,或者匿名内部类。使得Handler默认持有外部类的引用。在Activity销毁时,由于Handler可能有未执行完/正在执行的Message。导致Handler持有Activity...

weixin_31570865的博客 1171

毕业设计采矿工程专业兴无煤矿南采区120万吨初步设计说明.doc

毕业设计采矿工程专业兴无煤矿南采区120万吨初步设计说明.doc

2020年深圳市建筑体块数据.zip

建筑物屋顶矢量数据,shp格式,38万栋建筑,WGS84地理坐标,包含每栋建筑面积,单位平方米,可通过GIS计算几何计算经纬度

上一篇: Android多线程全面解析:IntentService用法&源码
下一篇: 怎样减少 Android 应用包 60% 的大小?
aptentity
博客等级 码龄20年 54粉丝 40原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值