[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();}

注释中明确的指出当消息队列空闲时会执行IdelHandlerqueueIdle()方法,该方法返回一个boolean值, 如果为false则执行完毕之后移除这条消息, 如果为true则保留,等到下次空闲时会再次执行,

下面看下MessageQueuenext()方法可以发现确实是这样。

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带来不同结果

目前可以想到的场景:

  1. Activity启动优化:onCreate,onStart,onResume中耗时较短但非必要的代码可以放到IdleHandler中执行,减少启动时间
  2. 想要一个View绘制完成之后添加其他依赖于这个ViewView,当然这个View#post()也能实现,区别就是前者会在消息队列空闲时执行。
  3. 发生一个返回trueIdleHandler,在里面让某个View不停闪烁,这样当用户发呆时就可以诱导用户点击这个View,这也是种很酷的操作。
  4. 一些第三方库中使用,比如LeakCanary,Glide中使用到,具体可以自行去查看。

Answer2:

这个IdleHandler,它是声明在MessageQueue里面的一个接口,所以我们可以猜想到它跟MessageQueue一定有关系,这个接口只有一个方法:queueIdle,字面意思就是队列空闲。 看MessageQueue的源码可以发现有两处关于IdleHandler的声明,分别是:

  • 存放IdleHandlerArrayList(mIdleHandlers)
  • 还有一个IdleHandler数组(mPendingIdleHandlers)

后面的数组,它里面放的IdleHandler实例都是临时的,也就是每次使用完(调用了queueIdle方法)之后,都会置空(mPendingIdleHandlers[i]=null) 那它们会在什么时候用到呢? 就是在MessageQueuenext方法里面
大概流程是这样的:
1.如果本次循环拿到的Message为空,或者!这个Message是一个延时的消息而且还没到指定触发时间,那么就认定当前的队列为空闲时间。
2.接着会遍历mPendingIdleHandlers数组(这个数组里面的元素每次都会到mIdleHandlers中去拿)来调用每一个IdleHandler实例的queueIdle方法。
3.如果这个方法返回false的话,那么这个实例就会从mIdleHandlers中移除,也就是当下次队列空闲的时候,不会继续回调它的queueIdle方法了。

来看看它在源码里的使用场景:
比如在ActivityThread中,就有一个名叫GcIdler的内部类,实现了IdleHandler接口。 它在queueIdle方法被回调时,会做强行GC的操作(即调用BinderInternalfaceGc方法),但强行GC的前提是与上一次强行GC至少相隔5秒以上。

那这个GcIdler会在什么时候使用呢?
ActivityThreadmH(Handler)收到GC_WHEN_IDLE消息之后。

何时会收到GC_WHEN_IDLE消息?
AMS(ActivityManagerService)中的这两个方法被调用之后:

  • doLowMemReportIfNeededLocked,这个方法看名字就知道是不够内存的时候调用了。
  • activityIdle,这个方法呢,就是当ActivityThreadhandleResumeActivity方法被调用时(ActivityonResume方法也是在这方法里面回调)调用的。

Answer3:

IdleHandler:空闲监听器(就好像我没事做了,在群里发了个表情,这时候其他人就知道我很闲了) 在每次next获取消息进行处理时,发现没得可以处理的消息(队列空,只有延时消息并且没到时间,同步阻塞时没有异步消息)都会通知这些订阅者。

适合做一些可有可无的东西,因为这个通知太不稳定了(就像别人说过几天请你吃饭,你要真傻等着估计能饿死)

Answer4:

去看了MessageQueuenext方法的源码,是在MessageQueue空闲(当MQ中Message消息全部执行完毕或者处理一个延时消息)时调用。

系统还在这几个地方应用了:

  1. Activity onResume 以及view初始化完成之后调用
  2. 强行GC,当内存不足时调用
  3. TTS合成之后发生广播
  4. Activity onCreate()执行前添加
  5. 在键盘相关调用

结合系统的使用场景,推测一下,可以做UI操作,不能太耗时,调用的时机比较模糊关联性不能太强。

最后

如果你看到了这里,觉得文章写得不错就给个呗?如果你觉得那里值得改进的,请给我留言。一定会认真查询,修正不足。

希望读到这的您能转发分享关注一下我,以后还会更新技术干货,谢谢您的支持!

加入Android开发交流群(820198451)还可以免费获取更多架构资料和面试专题资料

Android架构师之路很漫长,一起共勉吧!


Android:Handler中的Idle Handler相关推荐

  1. Android 开发过程中平时遇到的一些问题及总结

    相信大家都有面试的经历,相对比面试官的问的一些问题其实都是基础的知识,但就是一些基础的知识我们也不是很完美的回答出来,我们也知道现在的开发人员很多,一家公司一个岗位就会有很多的开发者投递,在那么多开发 ...

  2. Android Handler中的handleMessage方法和post方法之源码剖析

    我们都知道,在子线程中进行UI操作(更新UI控件)包括以下四种方法: 1.Handler的handlerMessage()方法. 2.Handler的post()方法. 3.View的post()方法 ...

  3. Android开发中的Handler和多线程

    在Android开发中我们常常用到Handler这个类去处理消息队列中的消息,以下这个例子实现的是利用Handler传递一个消息给线程,线程运行run()方法去更新进度条的进度,以下是源代码: pub ...

  4. 【Android 异步操作】手写 Handler ( Message 消息 | ThreadLocal 线程本地变量 | Looper 中的消息队列 MessageQueue )

    文章目录 一.Message 消息 二.ThreadLocal 线程本地变量 三.Looper 中的消息队列 MessageQueue 一.Message 消息 模仿 Android 中的 Messa ...

  5. Android开发中Handler的经典总结

    当应用程序启动时,Android首先会开启一个主线程(也就是UI线程),主线程为管理界面中的UI控件,进行事件分发. AD: 一.Handler的定义: 主要接受子线程发送的数据, 并用此数据配合主线 ...

  6. epoll监听文件_介绍一下 Android Handler 中的 epoll 机制?

    介绍一下 Android Handler 中的 epoll 机制? 目录: IO 多路复用 select.poll.epoll 对比 epoll API epoll 使用示例 Handler 中的 e ...

  7. android打地鼠设计报告,android开发中利用handler制作一个打地鼠小游戏

    android开发中利用handler制作一个打地鼠小游戏 发布时间:2020-11-25 15:21:11 来源:亿速云 阅读:136 作者:Leah 这期内容当中小编将会给大家带来有关androi ...

  8. Android Handler中post方法与send方法的区别及使用

    目录 概述 Handler使用sendMessage方法 Handler使用post方法 post方法与send方法的区别 全部代码 效果图 后记 概述 Handler机制是Android中线程通信的 ...

  9. Android如何让Handler中内部run停止(runnable/thread)

    [声明]此文转载自:http://www.bubuko.com/infodetail-669650.html --尊重作者,知识无价,交流无限! 一.先看图片,一目了然: 二.再看代码,了然于胸: A ...

最新文章

  1. 简易在线实验室管理系统
  2. 线性代数行变换与列变换
  3. 联想拯救者开机自动修复_设计师群体的创作利器,联想拯救者Y9000X 2021图赏
  4. 局域网访问php forbidden,PHP访问时Forbidden403错误
  5. 在Docker中的ubuntu中安装Python3和Pip
  6. S3C2410 bootloader ----VIVI阅读笔记 (转)下
  7. php-fpm哪里下载_如何在centos系统下找到php-fpm的位置 - 翟码农技术博客
  8. android u盘加载_如何获取Android系统挂载U盘的路径
  9. 新零售引发全球关注 阿里巴巴获零售业年度全球最大奖
  10. 原理图端口符号_电气的原理图和接线图的区别,今天终于弄明白了!
  11. arcgis python 百度网盘 视频_arcgis软件零基础入门视频教程27讲百度网盘链接
  12. 数据分析-常用分析方法-(1)描述性分析-用Excel实现
  13. C++实现经典同步问题(生产者消费者、读者写者、哲学家进餐、吸烟者问题)
  14. 将一个文件伪装在另一个文件下
  15. CF949D Curfew(贪心)
  16. SpringBoot Mybatis 读写分离配置
  17. Android系统Surface机制的SurfaceFlinger服务简要介绍和学习计划
  18. Java 核心技术卷 II(第 8 版) – 读书笔记 – 第 1 章(下)
  19. 常用 APP URL Scheme
  20. t30服务器u盘如何安装系统,无光驱使用U盘/Ukey/闪存/启动电脑安装winxp sp3的操作系统--梦飞翔的地方(梦翔天空)...

热门文章

  1. Java File文件操作
  2. 在Mysql中无符号是什么意思博客_mysql中的unsigned是什么意思???
  3. 如何将代码上传到gitee
  4. gitee提交代码到仓库
  5. LDA(Linear Discriminant Analysis)的原理详解
  6. 求助大神 VMware 卸载
  7. 数据项、数据字典、模式等基本概念辨析 数据库系统结构
  8. Matlab透视变换
  9. chart.js基本知识——调整图表尺寸
  10. 微信小程序 image图片组件实现宽度固定 高度自适应