实用干货!快速定位解决,新思路解决一个跟 Handler 有关的奇葩 Bug

2021-01-06 17:55:34 浏览数 (1)

背景

最近接手新项目,遇到了一个跟 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 中已收录,大家可以自行获取。

0 人点赞