干货!教你快速定位,新思路解决Android Handler 相关Bug

背景

最近接手新项目,遇到了一个跟 Handler 有关的 Bug,在解决过程中耗费了挺多时间的,最后通过另外的思路解决了。

在此通过本篇文章分享给大家,也为大家后面遇到 Handler 相关问题时能快速定位解决。

问题描述

问题点在于 Handler 发送的消息没有在 handleMessage 收到。

当然发送消息的地方和接受消息的地方不是同一个文件。

可以认为 Handler 通过 HashMap 统一管理起来。

思路 1

会不会发送的 Handler 跟接收的 Handler 不是同一个?

毕竟是通过 HashMap 管理,有可能被替换了?

验证方法:打印一下 Handler 的引用就可以确认,结果是同一个 Handler。

思路 2

会不会发送的消息被 remove 掉了?

验证方法:通过新引入一个唯一的 msg.what 来确认,结果也没有收到。

思路 3

    /**
     * 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学习资源:Android源码解析、Android第三方库源码笔记、Android进阶架构师七大专题学习、历年BAT面试题解析包、Android大佬学习笔记等等,这些内容均免费分享给大家,需要完整版的朋友,点这里可以看到全部内容

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章