Handler---4部曲---4.細節補充

Handler---4部曲---1. 總體流程
Handler---4部曲---2. ThreadLocal 存儲主流程
Handler---4部曲---3. MessageQueue隊列
Handler---4部曲---4.細節補充

一. 主線程Looper.loop()死循環阻塞了,爲何Activity的裏代碼還能執行,爲什麼不會ANR.

  1. 看過Activity的啓動流程就知道了, Activity的生命週期全部運行在handler中, 也屬於一個msg, 包括一些點擊事件等, 也是msg.
  2. ANR的判斷, 並不是主線程loop裏判斷的,而是在別的地方.

二. Handler發送消息時,到底哪個線程的Looper處理的, 回調方法handleMessage在哪個線程?

由Hander初始化時的Looper對象決定的.

  1. 如下:無論在任何地方初始化Handler,最終回調運行在主線程.
new Handler(Looper.getMainLooper())
  1. 如下:最終回調運行在當前Handler初始化的線程.
new Handler(Looper.myLooper())

Handler的空參構造函數標記成已過時,就是爲了讓調用者明確,在哪個線程回調時.

三 主線程 什麼時候進行休眠? 什麼時候被喚醒?

關鍵標記: MessageQueue中的成員變量:;
mBlocked ---> true主線程休眠中 , false沒休眠

通過上一篇文章我們知道, 主線程進入休眠的條件:

//取出的消息msg ---->包括同步或異步
msg==null  ||  沒到msg執行的時間  &&  沒有空閒消息   

怎麼喚醒:
調用nativeWake方法即可喚醒,一共3個地方調用, 如下圖:

1. enqueueMessage方法,msg入隊的時候


①. 當前狀態休眠 && 新消息(同步或異步)可以馬上執行的時候,需要喚醒.
②. 當前狀態休眠 && 新消息不需要馬上執行 && 隊列頭是同步屏障消息 && 新加進來的消息異步消息


2. removeSyncBarrier方法,刪除異步消息的時候

3.quit方法, 放棄消息, 準備退出的時候

疑問:mQuitAllowed什麼時候賦值的?
①. MessageQueue構造方法賦值

②. Looper中的構造方法賦值.


③. 主線程和子線程 Looper 初始化的區別


四. 子線程和主線程消息處理有什麼不一樣的?

通過上面可以知道.

  1. Looper初始化的時候, 傳入參數不同
  2. 主線程允許退出,子線程不允許退出
  3. next()方法返回值,子線程調用quit方法後,會喚醒當前線程,next()返回null, 會退出loop循環.
  4. 子線程無法處理mIdleHandlers空閒任務, 因爲在next()裏:
if (mQuitting) {  子線程會進入這裏
      return null;
}

...後面纔是處理mIdleHandlers空間任務.

4.子線程使用完必須釋放資源(任意一個), 否則會造成內存泄漏.

        //mQueue.quit(false);
        handler().getLooper().quit();
        //mQueue.quit(true);
        handler().getLooper().quitSafely();

五. 任何線程 ---> 指定子線程發送消息.

注意: 退出 釋放內存

六. 如何發送 需要緊急處理的msg?

MessageQueue.next()方法可知,隊列頭是同步屏障消息時,優先處理異步消息.


所以關鍵有2步:

  1. 添加同步屏障消息到隊列頭
postSyncBarrier()
  1. 我們緊急處理的消息--->設置爲異步消息

補充:
①. 方法調用,可能需要反射
②. 同步屏障消息,用完記得刪除, 上一篇文章提到過

七. Message 裏面的緩衝池.

  1. 取消息的時候, 直接從緩衝池裏拿.


  2. 釋放的時候, 如果緩衝池沒有滿, 加到緩衝池最前面


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