標籤:table 模型 handle 通過 bin 標記 無限迴圈 構造 uem
接上篇《android開發藝術探索》讀書筆記(九)--四大組件
No1:
訊息佇列MessageQueue的內部儲存結構並不是真正的隊列,而是採用單鏈表的資料結構來儲存訊息列表,因為單鏈表在插入和刪除上比較有優勢
No2:
ThreadLocal可以在不同的線程中互不干擾地儲存並提供資料,通過ThreadLocal可以輕鬆擷取每個線程的Looper。
No3:
線程預設是沒有Looper的,如果需要使用Handler就必須為線程建立Looper。
No4:
我們經常提到的主線程,也叫UI線程,它就是ActivityThread,ActivityThread被建立時就會初始化Looper,這也是在主線程中預設可以使用Handler的原因。
No5:
系統為什麼不允許在子線程中訪問UI呢?
1)因為Android的UI控制項不是安全執行緒的,如果在多線程中並發訪問可能會導致UI控制項處於不可預期的狀態
2)如果系統對UI控制項的訪問加上鎖機制有兩個缺點
21)會讓UI訪問的邏輯變得複雜
22)鎖機制會降低UI訪問的效率,因為鎖機制會阻塞某些線程的執行
No6:
1)當某些資料是以線程為範圍並且不同線程具有不同的資料副本的時候,就可以考慮採用ThreadLocal。比如Looper、ActivityThread、以及AMS中
2)ThreadLocal另一個使用情境是複雜邏輯下的對象傳遞,比如監聽器的傳遞。因為參數傳遞會使程式設計糟糕,而靜態變數不具有可擴充性
No7:
為何不同線程訪問同一個ThreadLocal得到的資料是不一樣的?
因為不同線程訪問同一個ThreadLocal的get方法,ThreadLocal內部會從各自的線程中取出一個數組,然後再從線程中根據當前ThreadLocal的索引去尋找出對應的value值。
No8:
Android訊息機制:
1)ThreadLocal工作原理:set方法、put方法、get方法(table[index+1]=value)
2)訊息佇列(MessageQueue)工作原理:插入enqueueMessage、讀取並刪除next(一個無限迴圈的方法)
3)Looper工作原理:構造方法(建立一個MessageQueue,儲存當前線程對象),Looper.prepare()(建立一個Looper),Looper.loop()(開啟訊息死迴圈,跳出迴圈唯一方式是next方法返回null),quit方法(終止迴圈,否則一直等待)
4)Handler工作原理:sendMessage發送訊息、dispatchMessage-->handleMessage處理訊息
No9:
Looper.getMainLooper可以在任何地方擷取到主線程的Looper
No10:
當Looper的quit方法被調用時,Looper就會調用MessageQueue的quit或者quitSafely方法來通知訊息隊列退出,當訊息佇列被標記為退出狀態時,它的next方法就會返回null。
No11:
Handler發送訊息的過程僅僅是向訊息佇列中插入了一條訊息,MessageQueue的next方法就會返回這條訊息給Looper,Looper收到訊息後就開始處理了,最終訊息由Looper交由Handler處理,即Handler的dispatchMessage方法會被調用,這時Handler就進入了處理訊息的階段。
No12:
主線程訊息迴圈:Android的主線程就是ActivityThread,主線程的入口方法為main,在main方法中系統會通過Looper.prepareMainLooper()來建立主線程的Looper以及MessageQueue,並通過Looper.loop()來開啟主線程的訊息迴圈。主線程的Handler是ActivityThread.H
No13:
主線程的訊息迴圈模型:
ActivityThread通過ApplicationThread和AMS進行處理序間通訊,AMS以處理序間通訊的方式完成ActivityThread的請求後會回調ApplicationThread中的Binder方法,然後ApplicationThread會向H發送訊息,H收到訊息後會將ApplicationThread中的邏輯切換到ActivityThread中去執行,即切換到主線程中去執行。
《android開發藝術探索》讀書筆記(十)--Android的訊息機制