Android:Handler中的Idle Handler
[Android] Handler中的IdleHandler
抛出
Handler
中的IdleHandler
- 它有什么能力?
- 它有什么用处?
- 能想到一些合适的场景吗?
Answer1:
首先看下源码的注释
/*** Callback interface for discovering when a thread is going to block* waiting for more messages.*/public static interface IdleHandler {/*** Called when the message queue has run out of messages and will now* wait for more. Return true to keep your idle handler active, false* to have it removed. This may be called if there are still messages* pending in the queue, but they are all scheduled to be dispatched* after the current time.*/boolean queueIdle();}
注释中明确的指出当消息队列空闲时会执行IdelHandler
的queueIdle()
方法,该方法返回一个boolean
值, 如果为false
则执行完毕之后移除这条消息, 如果为true
则保留,等到下次空闲时会再次执行,
下面看下MessageQueue
的next()
方法可以发现确实是这样。
Message next() {......for (;;) {......synchronized (this) {// 此处为正常消息队列的处理......if (mQuitting) {dispose();return null;}if (pendingIdleHandlerCount < 0&& (mMessages == null || now < mMessages.when)) {pendingIdleHandlerCount = mIdleHandlers.size();}if (pendingIdleHandlerCount <= 0) {// No idle handlers to run. Loop and wait some more.mBlocked = true;continue;}if (mPendingIdleHandlers == null) {mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];}mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);}for (int i = 0; i < pendingIdleHandlerCount; i++) {final IdleHandler idler = mPendingIdleHandlers[i];mPendingIdleHandlers[i] = null; // release the reference to the handlerboolean keep = false;try {keep = idler.queueIdle();} catch (Throwable t) {Log.wtf(TAG, "IdleHandler threw exception", t);}if (!keep) {synchronized (this) {mIdleHandlers.remove(idler);}}}pendingIdleHandlerCount = 0;nextPollTimeoutMillis = 0;}}
处理完IdleHandler
后会将nextPollTimeoutMillis
设置为0
,也就是不阻塞消息队列, 当然要注意这里执行的代码同样不能太耗时,因为它是同步执行的,如果太耗时肯定会影响后面的message
执行。 能力大概就是上面讲的这样,那么能力决定用处,用处从本质上讲就是趁着消息队列空闲的时候干点事情,当然具体用处还是要看具体的处理。 要使用IdleHandler
只需要调用MessageQueue#addIdleHandler(IdleHandler handler)
方法即可
合适场景可以从下面几点出发:
- 消息队列相关
- 主线程能干的事情
- 返回true和false带来不同结果
目前可以想到的场景:
Activity
启动优化:onCreate,onStart,onResume
中耗时较短但非必要的代码可以放到IdleHandler
中执行,减少启动时间- 想要一个View绘制完成之后添加其他依赖于这个
View
的View
,当然这个View#post()
也能实现,区别就是前者会在消息队列空闲时执行。 - 发生一个返回
true
的IdleHandler
,在里面让某个View
不停闪烁,这样当用户发呆时就可以诱导用户点击这个View
,这也是种很酷的操作。 - 一些第三方库中使用,比如LeakCanary,Glide中使用到,具体可以自行去查看。
Answer2:
这个IdleHandler
,它是声明在MessageQueue
里面的一个接口,所以我们可以猜想到它跟MessageQueue
一定有关系,这个接口只有一个方法:queueIdle
,字面意思就是队列空闲。 看MessageQueue
的源码可以发现有两处关于IdleHandler
的声明,分别是:
- 存放
IdleHandler
的ArrayList(mIdleHandlers)
- 还有一个
IdleHandler
数组(mPendingIdleHandlers)
后面的数组,它里面放的IdleHandler
实例都是临时的,也就是每次使用完(调用了queueIdle
方法)之后,都会置空(mPendingIdleHandlers[i]=null)
那它们会在什么时候用到呢? 就是在MessageQueue
的next
方法里面
大概流程是这样的:
1.如果本次循环拿到的Message
为空,或者!这个Message
是一个延时的消息而且还没到指定触发时间,那么就认定当前的队列为空闲时间。
2.接着会遍历mPendingIdleHandlers
数组(这个数组里面的元素每次都会到mIdleHandlers中去拿)来调用每一个IdleHandler
实例的queueIdle
方法。
3.如果这个方法返回false
的话,那么这个实例就会从mIdleHandlers
中移除,也就是当下次队列空闲的时候,不会继续回调它的queueIdle方法了。
来看看它在源码里的使用场景:
比如在ActivityThread
中,就有一个名叫GcIdler
的内部类,实现了IdleHandler
接口。 它在queueIdle
方法被回调时,会做强行GC
的操作(即调用BinderInternal
的faceGc
方法),但强行GC
的前提是与上一次强行GC
至少相隔5秒以上。
那这个GcIdler会在什么时候使用呢?
当ActivityThread
的mH
(Handler)收到GC_WHEN_IDLE
消息之后。
何时会收到GC_WHEN_IDLE
消息?
当AMS
(ActivityManagerService)中的这两个方法被调用之后:
doLowMemReportIfNeededLocked
,这个方法看名字就知道是不够内存的时候调用了。activityIdle
,这个方法呢,就是当ActivityThread
的handleResumeActivity
方法被调用时(Activity
的onResume
方法也是在这方法里面回调)调用的。
Answer3:
IdleHandler
:空闲监听器(就好像我没事做了,在群里发了个表情,这时候其他人就知道我很闲了) 在每次next获取消息进行处理时,发现没得可以处理的消息(队列空,只有延时消息并且没到时间,同步阻塞时没有异步消息)都会通知这些订阅者。
适合做一些可有可无的东西,因为这个通知太不稳定了(就像别人说过几天请你吃饭,你要真傻等着估计能饿死)
Answer4:
去看了MessageQueue
的next
方法的源码,是在MessageQueue
空闲(当MQ中Message
消息全部执行完毕或者处理一个延时消息)时调用。
系统还在这几个地方应用了:
Activity onResume
以及view
初始化完成之后调用- 强行
GC
,当内存不足时调用 TTS
合成之后发生广播- 在
Activity onCreate()
执行前添加 - 在键盘相关调用
结合系统的使用场景,推测一下,可以做UI操作,不能太耗时,调用的时机比较模糊关联性不能太强。
最后
如果你看到了这里,觉得文章写得不错就给个赞呗?如果你觉得那里值得改进的,请给我留言。一定会认真查询,修正不足。
希望读到这的您能转发分享和关注一下我,以后还会更新技术干货,谢谢您的支持!
加入Android开发交流群(820198451)还可以免费获取更多架构资料和面试专题资料
Android架构师之路很漫长,一起共勉吧!
Android:Handler中的Idle Handler相关推荐
- Android 开发过程中平时遇到的一些问题及总结
相信大家都有面试的经历,相对比面试官的问的一些问题其实都是基础的知识,但就是一些基础的知识我们也不是很完美的回答出来,我们也知道现在的开发人员很多,一家公司一个岗位就会有很多的开发者投递,在那么多开发 ...
- Android Handler中的handleMessage方法和post方法之源码剖析
我们都知道,在子线程中进行UI操作(更新UI控件)包括以下四种方法: 1.Handler的handlerMessage()方法. 2.Handler的post()方法. 3.View的post()方法 ...
- Android开发中的Handler和多线程
在Android开发中我们常常用到Handler这个类去处理消息队列中的消息,以下这个例子实现的是利用Handler传递一个消息给线程,线程运行run()方法去更新进度条的进度,以下是源代码: pub ...
- 【Android 异步操作】手写 Handler ( Message 消息 | ThreadLocal 线程本地变量 | Looper 中的消息队列 MessageQueue )
文章目录 一.Message 消息 二.ThreadLocal 线程本地变量 三.Looper 中的消息队列 MessageQueue 一.Message 消息 模仿 Android 中的 Messa ...
- Android开发中Handler的经典总结
当应用程序启动时,Android首先会开启一个主线程(也就是UI线程),主线程为管理界面中的UI控件,进行事件分发. AD: 一.Handler的定义: 主要接受子线程发送的数据, 并用此数据配合主线 ...
- epoll监听文件_介绍一下 Android Handler 中的 epoll 机制?
介绍一下 Android Handler 中的 epoll 机制? 目录: IO 多路复用 select.poll.epoll 对比 epoll API epoll 使用示例 Handler 中的 e ...
- android打地鼠设计报告,android开发中利用handler制作一个打地鼠小游戏
android开发中利用handler制作一个打地鼠小游戏 发布时间:2020-11-25 15:21:11 来源:亿速云 阅读:136 作者:Leah 这期内容当中小编将会给大家带来有关androi ...
- Android Handler中post方法与send方法的区别及使用
目录 概述 Handler使用sendMessage方法 Handler使用post方法 post方法与send方法的区别 全部代码 效果图 后记 概述 Handler机制是Android中线程通信的 ...
- Android如何让Handler中内部run停止(runnable/thread)
[声明]此文转载自:http://www.bubuko.com/infodetail-669650.html --尊重作者,知识无价,交流无限! 一.先看图片,一目了然: 二.再看代码,了然于胸: A ...
最新文章
- 简易在线实验室管理系统
- 线性代数行变换与列变换
- 联想拯救者开机自动修复_设计师群体的创作利器,联想拯救者Y9000X 2021图赏
- 局域网访问php forbidden,PHP访问时Forbidden403错误
- 在Docker中的ubuntu中安装Python3和Pip
- S3C2410 bootloader ----VIVI阅读笔记 (转)下
- php-fpm哪里下载_如何在centos系统下找到php-fpm的位置 - 翟码农技术博客
- android u盘加载_如何获取Android系统挂载U盘的路径
- 新零售引发全球关注 阿里巴巴获零售业年度全球最大奖
- 原理图端口符号_电气的原理图和接线图的区别,今天终于弄明白了!
- arcgis python 百度网盘 视频_arcgis软件零基础入门视频教程27讲百度网盘链接
- 数据分析-常用分析方法-(1)描述性分析-用Excel实现
- C++实现经典同步问题(生产者消费者、读者写者、哲学家进餐、吸烟者问题)
- 将一个文件伪装在另一个文件下
- CF949D Curfew(贪心)
- SpringBoot Mybatis 读写分离配置
- Android系统Surface机制的SurfaceFlinger服务简要介绍和学习计划
- Java 核心技术卷 II(第 8 版) – 读书笔记 – 第 1 章(下)
- 常用 APP URL Scheme
- t30服务器u盘如何安装系统,无光驱使用U盘/Ukey/闪存/启动电脑安装winxp sp3的操作系统--梦飞翔的地方(梦翔天空)...