乾貨!教你快速定位,新思路解決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大佬學習筆記等等,這些內容均免費分享給大家,需要完整版的朋友,點這裏可以看到全部內容

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