背景
最近接手新项目,遇到了一个跟 Handler 有关的 Bug,在解决过程中耗费了挺多时间的,最后通过另外的思路解决了。
在此通过本篇文章分享给大家,也为大家后面遇到 Handler 相关问题时能快速定位解决。
问题描述
问题点在于 Handler 发送的消息没有在 handleMessage 收到。
当然发送消息的地方和接受消息的地方不是同一个文件。
可以认为 Handler 通过 HashMap 统一管理起来。
思路 1
会不会发送的 Handler 跟接收的 Handler 不是同一个?
毕竟是通过 HashMap 管理,有可能被替换了?
验证方法:打印一下 Handler 的引用就可以确认,结果是同一个 Handler。
思路 2
会不会发送的消息被 remove 掉了?
验证方法:通过新引入一个唯一的 msg.what 来确认,结果也没有收到。
思路 3
代码语言:javascript复制 /**
* Sends a Message containing only the what value.
*
* @return Returns true if the message was successfully placed in to the
* message queue. Returns false on failure, usually because the
* looper processing the message queue is exiting.
*/
public final boolean sendEmptyMessage(int what)
{
return sendEmptyMessageDelayed(what, 0);
}
通过源码的注释,发现消息如果已经在队列,是不会再塞进去的,但是如果队列已经存在,也不应该收不到啊。
最后打印返回值也是正确的。
虽然这个思路没有解决问题,但是由于这个,打开了另一个思路,那就是会不会队列阻塞了,消息卡住了?
最终验证方法
因此最终通过引入 IdleHandler 来验证到底消息队列是不是出问题了,没有空闲消息回调。
关于 IdleHandler,我简单说明下,一般是在 Handler 空闲时会回调,如果你监听后没有移除,会一直回调。
用法之一是延迟初始化,提高界面渲染速度。
更多资料见:
IdleHandler
最终确认了,在这个发送消息的线程(子线程)里面使用 IdleHandler 没有回调,而原先的 Handler 是在主线程构建的。
因此根源是由于修改了 Handler 的线程,而所在的子线程消息不断的产生消息造成队列可能一直被占用,因此新发的消息收不到。
Android 开发相关源码精编解析
随着Android开发行业逐渐饱和,对Android开发者的面试要求也越来越高,是否掌握底层源码,便是考验一名Android开发者的重要一环。面试被问到源码问题答不出来,会掉身价、砍薪资尚且不谈,甚至连面试都过不了!
网上各类源码解析的文章博客五花八门、良莠不齐。杂乱、要么内容质量太浅,零散、碎片化,总看着看着就衔接不上了。
所以特意将我在疫情期间花了4个月整理出来的《Android 开发相关源码精编解析》分享出来大家
由于内容较多,避免影响到大家的阅读体验,在此只截图展示目录部分,487详细完整版的《Android 开发相关源码精编解析》电子书文档免费领取~
目录:一共18节,487页PDF,包括MMKV 源码,ARouter 源码,AsyncTask 源码,Volley 源码,Retrofit 源码,OkHttp 源码,ButterKnife 源码,Okio 源码,SharedPreferences 源码,EventBus 源码,Android 自定义注解初探,View 的工作机制源码分析,Android 触摸事件分发机制源码分析,Android 按键事件分发机制源码分析,深入解析 Handler 源码,深入解析 Binder 源码,深入解析 JNI 源码,深入解析 Glide 源码。
《Android 开发相关源码精编解析》电子书文档领取方式: 以上内容均放在了开源项目:【github】 中已收录,大家可以自行获取。