Android Handler 避免内存泄漏的用法总结

扒一扒面试必问的Handler 前言 Handler作为Android代码编写以及面试时经常遇到的内容,有必要花个时间整理一下,毕竟写过的东西印象会更加深刻。 1.什么是Handler? 1.1 定义 源码里面捞出来的内容,英文不难看懂。主要就是说每个Handler会和每个线程以及线程对应的消息队列相绑定。之后消息就可通过Handler在线程之间传递。 A Handler allows you to send and process {@link Message} and Runnable objects associated 阅读详情

原文地址:https://www.cnblogs.com/liyiran/p/5228771.html

http://blog.youkuaiyun.com/stzy00/article/details/43988213


Handler是由系统所提供的一种异步消息处理的常用方式,一般情况下不会发生内存泄露.

但既然是调优,当在A_Activity中使用handler发送了几个消息,然后又跳到B_Activity,这个时候如果我们想结束之前在A_Activity中发出的消息,不再占用多余的队列空间.怎么办呢?


原来,Handler中已经提供了一个removeCallbacksAndMessages去清除Message和Runnable:

[java]  view plain  copy
  1. handler.removeCallbacksAndMessages(null);  

将方法参数设为null.


在Activity的销毁方法onDestroy()中调用该方法即可.


题外话:

熟悉Activity的生命周期是能让应用在性能调优时达到更好的实现方式. 比如onDestroy() 方法,onPause()方法等等, Activity销毁前生命周期会进入onDestroy(),当前Activity所用过且不再需要的占用内存的资源可以在这里进行一些处理, 比如将不再使用的视图资源清除掉,将正在访问而不再需要的网络连接给终止掉,将消息队列中不再需要的消息清除等等.这样当不断打开新的页面Activity,也能将应用多余的内存缓存尽量减少一些达到调优的目的.


-------------------------


Android开发经常会用到handler,但是我们发现每次使用Handler都会出现:This Handler class should be static or leaks might occur(null)这样的提示。Android lint就是为了提示我们,这样使用Handler会容易造成内存泄漏。但是你会发现其实改成static并没有什么用。因为这并没有解决这个问题的根本。

  首先,我们得确认,为什么会有内存泄漏?因为Handler是基于消息的。每次new 出Handler,都会创建一个消息队列用于处理你使用handler发送的消息,形如:handler.send***Message。由于消息的发送总是会有先来后到的区别(如果只是这样都还好,毕竟再慢也不会太久,总归可以跑完,可能会延迟个几秒),但是如果你使用的是sendMessageDelayed(Message msg, long delayMillis)或postDelayed(Runnable r, long delayMillis)等发送延迟消息的时候,那基本内存泄漏发生的概率已经在90%以上了。

     我举个通常的例子,就是我们在Activity中使用handler来更新UI控件,这是比较常见的。

复制代码
 1 public class DemoActivity extends Activity {
 2 
 3     private Handler mHandler; 
 4 
 5     protected void onCreate(Bundle savedInstanceState) {
 6         mHandler = new Handler();
 7 
 8      mHandler.postDelayed(new Runnable() {
 9        Log.i("wytings","-----------postDelayed-------");
10             view.setVisibility(View.GONE);
11         }, 50000);
12         ...
13     }
14   
复制代码

      如果我们疯狂的对这个Activity进行横屏和竖屏切换的话,那么Activity就会不断的被销毁和重建。理论上被关闭的Activity应该会再特定时候被回收,也就是我们的内存会在一定的范围内上下起伏,但是实际上,会发现消耗的内存会随着切换横屏的次数一直慢慢增加。这其实已经说明我们的内存泄漏了,如果你会查看内存,你会发现里面有成堆的DemoActivity实例没办法回收。

  这是因为view中使用的Context就是当前的Activity,而这个runnable一旦被post,就会一直存在于队列里面,直到时间到了,被执行。意思是这个时间段内Activity即使已经被destroy了但是这个对象还是没办法回收,你会发现50秒好,会有一堆"-----------postDelayed-------"的log打印出来,虽然你已经被这个应用关闭了并且你以为即使打印也应该只打印一次……

  那怎么样才可以避免这中问题呢,如果你网上一搜你会看到很多关于弱引用的文章。这确实是一个解决的办法。其原理就是让所有在handler里面使用的对象都变成弱引用,目的就是为了可以在Android回收内存的时候,可以直接回收掉。我真觉得如果只是写这种办法的人,绝对是属于拷贝党,因为这完全是就事论事。你想想就明白,我们写这个Handler是因为我们要使用它。怎么可以通过这种弱引用的办法去处理这类问题呢?让JVM想回收就回收?!如果这样,那我们还需要在使用Bitmap的时候,recycle()干嘛,还不如直接弄成软引用得了。

这里需要再插播一下关于Java里面引用的知识:

强引用(Strong Reference) 默认引用。如果一个对象具有强引用,垃圾回收器绝不会回收它。在内存空 间不足时,Java虚拟机宁愿抛出OutOfMemory的错误,使程序异常终止,也不会强引用的对象来解决内存不足问题。
软引用(SoftReference) 如果内存空间足够,垃圾回收器就不会回收它,如果内存空间不足了,就会回收这些对象的内存。
弱引用(WeakReference) 在垃圾回收器一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。
虚引用(PhantomReference) 如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收。

 

      如果你运气好,你会碰到一些除了写弱引用这个方法后,还有一个就是handler.removeCallbacksAndMessages(null);,就是移除所有的消息和回调,简单一句话就是清空了消息队列。注意,不要以为你post的是个Runnable或者只是sendEmptyMessage。你可以看一下源码,在handler里面都是会把这些转成正统的Message,放入消息队列里面,所以清空队列就意味着这个Handler直接被打成原型了,当然也就可以回收了。

  所以,我觉得最好的办法就是你在使用Handler的时候,在外面的Activity或者Fragment中的关闭方法中,如onDestroy中调用一下handler.removeCallbacksAndMessages(null);就可以了,不应该改成软引用。




彻底卸载Ubuntu双系统,并完美回收100G空间给D盘 本文记录了安全卸载Ubuntu双系统并回收磁盘空间的全过程。作者首先通过Windows命令行彻底清除Ubuntu启动项,避免GRUB引导报错;随后在磁盘管理中删除Linux分区,将100G未分配空间合并至相邻的D盘。针对C盘空间不足问题,作者采用Dism++清理系统文件,并将用户文档、聊天记录等迁移至扩容后的D盘。最终实现了引导纯净、空间合理分配的目标,特别强调分区扩展必须遵循"相邻原则",建议通过间接迁移而非直接扩容来优化系统盘空间管理。 阅读详情

相关推荐

STM32U575 ADC+DMA+UART数据采集实战:CubeMX配置避坑与代码实现

在嵌入式开发中,ADC采集与DMA传输是提升系统实时性的关键技术。通过DMA将ADC数据直接搬运到内存,可大幅降低CPU占用,实现高效连续采样。结合UART的DMA发送,能进一步解放CPU,适用于工业采集、信号监测等场景。本文以STM32U575为例,详解CubeMX中ADC、DMA、UART的配置要点,包括时钟树、DMAMUX映射、循环模式等,并给出代码实现与常见问题排查,帮助开发者快速构建稳定的数据采集链路。

weixin_29194255的博客 170

Android removeCallbacksAndMessages解析

一、removeCallbacksAndMessages应用场景 当在A类初始化了一个Handler,使用的是主线程的Looper,用于发送延迟消息和主线程切换,当A类释放资源的时候调用removeCallbacksAndMessages(null),意思是清空当前Handler队列所有消息。因为不这样做会导致A类释放后还有可能执行Handler的那个延迟消息。 二、源码解析 void removeCallbacksAndMessages(Handler h, Object object) { if

分享Android开发知识 5372

[ESP32]:基于esp-modbus实现serial主机

[ESP32]:基于esp-modbus实现serial主机

LINKKEEE的博客 2569

Android:Handler

一个线程只有一个Looper,但可对应多个Handler,当通过Looper.prepare方法创建Looper时会调用ThreadLocal的get()方法来检查ThreadLocalMap中是否已经set过Looper。ActivityThread中的main()已经对Looper进行了prepar()操作,已经可以通过getMainLooper获取。

weixin_51109304的博客 2702

Code Composer Studio 12.0.0版本 官方例程导入实战指南

本文详细介绍了在Code Composer Studio 12.0.0版本中,如何利用内置的Resource Explorer工具高效导入官方例程的完整实战指南。通过分步讲解定位开发板、导入工程、配置编译器及调试验证等关键操作,帮助开发者快速上手TI微控制器开发,避免常见错误,有效提升学习与开发效率。

weixin_29169899的博客 122

手把手教你配置SAP PP供应区域(Supply Area):实现线边仓精准发料与物料流优化

本文详细解析了SAP PP供应区域(Supply Area)的配置方法,帮助企业实现线边仓精准发料与物料流优化。通过三级优先级逻辑和四步配置法,系统可自动识别最优组件来源位置,显著提升生产订单处理效率和库存准确率。文章还提供了典型问题解决方案和性能优化技巧,适用于离散制造和重复制造场景。

weixin_29275257的博客 434

removeCallbacksAndMessages(null)的含义

一般在在onDestroy()方法中,使用了这个的代码: 如果参数为null的话,会将所有的Callbacks和Messages全部清除掉。 这样做的好处是在Acticity退出的时候,可以避免内存泄露。 具体内存泄漏的东西参考我的Github: https://github.com/houzirui/HandlerLeakCanaryDemo

RuiMan的博客 4330

手搓ZLMediaKit实现拉流推流系列3(RK3588上YOLO系列拉流、MPP解码+编码、推流全流程)

 前段时间比较忙,一直没有时间补充后续的内容。今天终于抽出空来,立马进入码字环节:手搓ZLMediaKit实现拉流推流系列在本篇也终于迎来了完结篇,在本篇文章中,你将看到以下一整套完整流程:使用ZLMediaKit拉流---MPP解码---Yolo模型进行推理---MPP编码并推流。

m0_46303486的博客 2175

Android handler用法及分析

handler用法分析

Qq2179344的博客 1926

Ollama+FAISS+Embedding+Rerank+LLM 详细部署指南

下载安装Ollama 双击运行安装程序 安装完成后会自动启动服务 修改默认安装路径(避免C盘爆满) 或使用PowerShell: 验证安装 Linux系统部署: (二)准备模型 1. 拉取Embedding模型 2. 拉取LLM模型 注意:原文中提到的可能需要从自定义仓库拉取: 3. 下载Rerank模型 (三)安装依赖库 创建项目目录和虚拟环境: 二、主要功能实现 项目结构 (一)配置文件(config/config.yaml) (二)文本分块策略实现 创建 : (三)文档读取

AI技术改变世界 1582

HBV模型

据说mHM模型也是基于HBV模型原理。 网上不同版本的HBV模型稍有差别 def hbv_main(n_days, params, air_temp, prec, dpem): #n_days 模拟天数 #air_temp 每月温度 #prec 降水 #dpem 每月蒸发 Tsnow_thresh = 0.0 ca = 410. # Initialize arrays for the simiulation snow = np.zeros(air_temp.size

m0_46268055的博客 2332

Handler的removeCallbacksAndMessages怎么不好使了呢?

前言 此篇文章记录日常遇到的一个小坑:Handler的removeCallbacksAndMessages没生效。 正文 需求: 需求:有1-5个超时任务,如果某个任务在规定时间内完成,需要取消对应的超时任务; 这个需求并不复杂,如果是比较简单的延时任务,可以使用Handler.postDelayed添加延时任务,如果任务在预期内完成,可以通过Handler.removeCallbacksAndMessages删除掉对应的任务: Handler handler = new Handler(); // 添

珠穆朗玛小王子的博客 2387

【AI理论学习】手把手推导扩散模型:Diffusion Models(DDPM)

生成扩散模型DDPM如下图所示分为前向、逆向两个过程,它首先通过不断往原始清晰数据中添加噪声使其变成标准高斯噪声(前向过程),而后期望从标准高斯噪声中还原原始数据(逆向过程)。若能实现,那便可从已知的标准高斯分布中采样一个噪声数据,而后利用DDPM模型生成符合原始数据分布的新数据。 Diffusion模型包含两个过程:数学符号:y∝xy\propto xy∝x:y正比于x,即y随着x增大而线性增大。 条件概率:贝叶斯公式:p(A∣B)=p(B∣A)×p(A)p(B)p(A|B)=\frac{p(B|A)\

小哲的博客 1512

Handler消息传递机制分析

http://tommwq.tech/blog/2019/11/17/6 Handler的用途和用法 写过Android程序的人大概都会遇到ANR(Application Not Responding)。如果程序在一段时间内没有响应,系统就会弹出一个对话框,让用户选择继续等待或者强制关闭应用。为了避免ANR,我们需要把耗时的逻辑放到后台线程里执行。而后台线程无法更新界面。当任务完成后,如何根据任务执行情况更新界面呢?这就需要使用Handler。下面的例子展示了Handler的基本用法: packag

tq1086的博客 125

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

把Handler全身摸个遍,2021年大厂Android面经

final long now = SystemClock.uptimeMillis(); Message prevMsg = null; Message msg = mMessages; //… if (msg != null) { if (now < msg.when) { // Next message is not ready. Set a timeout to wake up when it is ready. nextPollTimeoutMillis = (int) Math.min(m

m0_65321095的博客 163

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

Handler 在 Android 开发中的高级用法:从基础到复杂场景

是处理线程间通信的核心组件,它基于消息队列机制,允许在不同线程间安全地传递任务。以下内容将从基础概念逐步过渡到高级应用场景,帮助您深入理解其用法。所有代码示例均使用 Java 语言,确保真实可靠。实际开发中,建议结合 Kotlin 协程或。是 Android 提供的工具类,封装了。需结合线程管理、内存优化和任务调度。通过以上内容,您可以从基础逐步掌握。在 Android 开发中,:在主线程更新 UI。仍是底层通信的基石。

2501_93878243的博客 490

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

Handler:你真的了解我吗?

提到handler,大家都想到些什么呢,切换线程?延时操作? 那么你是否了解IdleHandler,同步屏障,死循环的设计原理?以及由Handler机制衍生的IntentService,BlockCanary? 这次我们说下Android中最常见的Handler,通过解析面试点或者知识点,带你领略Handler内部的神奇之处。 先说下基本的用法和工作流程 用法很简单,定义一个handler,重写handleMessage方法处理消息,用send方法通知handler 但是主线程和其他线程用法却有点不一样.

积木点点滴滴 1088

java 消息传递机制_Handler消息传递机制分析

Handler的用途和用法写过Android程序的人大概都会遇到ANR(Application Not Responding)。如果程序在一段时间内没有响应,系统就会弹出一个对话框,让用户选择继续等待还是强制关闭应用。为了避免ANR,我们需要把耗时的逻辑放到后台线程里执行。但是后台线程无法更新界面。那么当任务完成后,如何根据结果更新界面呢?Handler就可以承担这个职责。下面的例子展示了Hand...

weixin_28803437的博客 293

对Handler的学习和理解

我对Handler的学习和理解 今天花了点时间研究了一下Handler的细节,来做一下总结: Handler的基本用法 Handler的大致实现机制 防止内存泄漏的优化 Handler的偏门用法 我掉进的一个坑 坑里面的玄机 Handler的基本用法 当我们在初学安卓的时候,就听说过一句话:“耗时操作要放在子线程中,更改UI操作要放在主线程中”,为什么呢?因为如果在主线程中出现耗时...

Yuke213的博客 292
上一篇: Android4.4以后第三方应用无法删除短信的解决方案
下一篇: Fragment嵌套ViewPager切换后数据消失ViewPager空白问题
dodod2012
博客等级 码龄15年 244粉丝 98原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值