編輯:關於android開發
很多以前掌握的知識,總是慢慢的再忘記,看來還是自己理解的不夠透徹,希望用博客的形式記錄下來。
說起android的消息機制,那不得不提Handler,它的中文含義就是控制者,處理者。
安卓上的關於Handler的文檔是這麼寫的:
Handler可以發送和處理Message,Runnable對象,並且與一個線程的MessageQueue關聯。
當創建了Handler實例,它就會綁定在創建它線程的消息隊列上。
首先在主線程中創建Handler的實例,與主線程的MessageQueue綁定,MessageQueue裡有一個輪詢器Looper,它會不斷的查看消息隊列是否有消息。如果有消息,就會把這個消息扔給Handler的handleMessage去處理。
這時,子線程拿到Handler對象,往主線程的MessageQueue發消息,消息隊列就有了消息,就會把消息扔給handleMessage去處理消息。
上面的過程,聽起來十分繞耳。為什麼要這麼做?在子線程中去處理不行嗎?
我們知道子線程一般是用於處理耗時的操作,是不可以更新UI的。
因為多線程同時去draw,去操作UI界面,UI界面實在不好控制。操作UI的動作必須要由主線程去做。
所以在子線程中碰見需要更新UI,我們可以使用android為我們提供的Handler。它的出現主要就是為了解決在子線程中無法訪問UI的矛盾。
而如果強行的在子線程去操作UI,可能會出現 “ android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.”的異常。
1,new Handler的時候,Handler究竟做了什麼?
Looper.mylooper()
Looper對象是從ThreadLocal集合中get得到的。那什麼時候,ThreadLocal把Looper對象set進去的呢?
在prepare方法中,創建了LoZ喎?http://www.Bkjia.com/kf/ware/vc/" target="_blank" class="keylink">vcGVyttTP86OssqLM7bzTtb3By7TmtKLXxUxvb3BlcrbUz/O1xFRocmVhZExvY2Fs1tChozxiciAvPg0KPGltZyBhbHQ9"這裡寫圖片描述" src="http://www.bkjia.com/uploads/allimg/160407/04145QQ6-5.png" title="\" />
而在new Looper的同時,同樣也創建了MessageQueue的實例。
而調用prepare方法的是prepareMainLooper。
在應用運行時,主線程ActivityThread產生並執行,而在主線程的main方法中,就會調用prepareMainLooper。
也就是說,在應用一啟動,就會去創建Looper,MessageQueue對象。而在Handler的構造方法中,是拿到已經創建好的Looper和MessageQueue。
2,Message消息對象
new Message可以直接創建消息對象。
通過handler.obtainMessage(有許多重載的方法)可以創建消息,翻看源碼可以得知,消息的創建全都是由obtain方法去處理。
這裡的sPool表示的是消息池中的第一條消息,當消息池中沒有消息時,就會new一個Message返回。
如果消息池中有的話,就廢物利用,把消息池中的消息返回。
而消息池中的消息是由Message本身來維護的,而不是MessageQueue。
消息池中的消息是這樣擺放的:
sPool表示是第一條消息,它指向著a。
Message m=sPool;
這時m也指向了a
sPool=m.next
sPool這時不再指向a,而是指向了下一個消息b。
m.next=null
sPoolSize--
a的next成員變量不再指向b,置為null。消息隊列的長度減減,返回消息池中的消息。
3,Looper處理消息的過程
子線程發送消息後,主線程的MessageQueue就有了消息。而消息的扔給Handler去處理,是需要Looper來輪詢的。
定位到Looper的輪詢消息的loop方法。
Message msg = queue.next(); // might block
..........
..........
..........
msg.target.dispatchMessage(msg);
從消息隊列中取出的消息交由了msg.target這個成員變量的dispatchMessage方法。
而msg.target是Handler類型的。那msg.target是怎麼傳遞進來的:
public static Message obtain(Handler h) {
Message m = obtain();
m.target = h;
return m;
}
該handler在創建Message時,賦予給Handler類型的target。
而在dispatchMessage中,會調用handleMessage。
而在主線程中,我們定義的handleMessage就會覆蓋該方法。
所以,Message對象就這樣一步一步的傳遞到了主線程Handler的handleMessage中。
結論就是:消息是由哪個Handler發送的,就由哪個Handler去處理。
記一次流量異常處理前兩天接到一個做開發的朋友電話,說他們客戶一台服務器開機後,所有一個網段的機器上網都變慢了,他遠程操作這台服務器也一卡一卡的。我第一反應就是機器被人攻擊
React-Native系列Android——Touch事件原理及狀態效果 Native原生相比於Hybrid或H5最大優點是具有流暢和復雜的交互效果,觸摸事件便是其
Android Activity各啟動模式的差異,androidactivityActivity共有四種啟動模式:standard,singleTop,singleTas
Android 手機衛士--自定義控件(獲取焦點的TextView),androidtextview本文地址:http://www.cnblogs.com/wuyudon