Handler使用主要作用一句話概括:線程間通信。
在日常開發中主要作用於兩方面:
1、在UI線程進行耗時操作時,將耗時操作拋到子線程進行處理,否則容易ANR。
2、在子線程中刷新UI。
一、Handler簡介
[Handler]、[Looper]、[MessageQueue] 和 [Message] 是組成Handler通信機制的基礎。
1.1Handler簡單使用
Handler的使用基本如以下代碼所示,或者繼承Handler重寫handleMessage,處理不同what標識的Message。不是本文討論的重點,不做過多敘述。
//創建子線程HandlerHandlerThread mHandlerThread = new HandlerThread("daqi"); mHandlerThread.start(); Handler mHandler = new Handler(mHandlerThread.getLooper());//創建MessageMessage message = mHandler.obtainMessage();//發送MessagemHandler.sendMessage(message);//postmHandler.post(new Runnable() { @Override public void run() { } });
1.2Handler工作流程
創建Handler,並綁定Looper -> Handler發送Message -> Message存儲到Looper的MessageQueue中 -> Looper在MessageQueue中拿取頂部Message -> 將Message發送給目標Handler
Handler、Looper、MessageQueue 和 Message的關係:
一個線程只能有一個Looper;
一個Handler只能綁定一個Looper;
多個Handler可以綁定同一個Looper;
一個Looper管理着一個MessageQueue。
MssageQueue作爲Message“收信箱”,收納着Handler發送的Message。
二、提出問題
帶着問題看源碼:
1、Looper如何確保線程中只有一個單例。
2、爲什麼建議使用Handler#obtainMessage()獲取Message對象,而不是直接new。
3、Handler的sendMessage() 和 post()有什麼區別。
4、Looper如何管理Message隊列(即先後發送不同延遲時間的Message,Message隊列如何排序)。
5、removeCallbacks、removeMessages 和 removeCallbacksAndMessages都移除了什麼。
推薦閱讀:阿里騰訊Android開發十年,到中年危機就只剩下這套移動架構體系了!
三、源碼分析
3.1、Looper機制
Handler在創建時,默認構造方法會綁定當前線程。所以我們選擇先從Handler的默認構造方法看起。
#Handler.java//無參構造函數public Handler() { this(null, false); }public Handler(Callback callback, boolean async) { //.... mLooper = Looper.myLooper(); if (mLooper == null) { throw new RuntimeException( "Can't create handler inside thread " + Thread.currentThread() + " that has not called Looper.prepare()"); } mQueue = mLooper.mQueue; mCallback = callback; }
創建Handler對象時,無參構造函數會獲取當前線程的Looper並獲取到其MessageQueue存儲到Handler自身變量中。
但我們也觀察到,如果沒有Looper的Thread中創建,會拋出RuntimeException,並告訴你該線程無Looper。
從Handler的默認構造方法中得知,在創建Handler前,需要先在當前線程中創建Looper對象和MessageQueue對象。而創建Looper對象和MessageQueue對象只需要調用如下方法:
Looper.prepare();Looper.loop();
prepare的意思是準備,即可以猜測Looper是在Looper#prepare()中初始化的,所以先從Looper#prepare()的源碼看起:
#Looper.java//主要用於作爲存儲的Looper實例的key。static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();private Looper(boolean quitAllowed) { mQueue = new MessageQueue(quitAllowed); mThread = Thread.currentThread(); }public static void prepare() { prepare(true); }private static void prepare(boolean quitAllowed) { //ThreadLocal#get()獲取當前線程的looper對象 if (sThreadLocal.get() != null) { //如果Looper已經實例化完,則會拋出異常 throw new RuntimeException("Only one Looper may be created per thread"); } //如果之前當前線程沒有初始化過Looper,則創建Looper並添加到sThreadLocal中 sThreadLocal.set(new Looper(quitAllowed)); }
我們發現Looper#prepare()調用重載函數Looper#prepare(boolean)。在這方法中,Looper會被初始化。查看Looper私有構造函數,發現Looper會初始化MessageQueue並存儲當前線程。
而Looper被初始化是有一個前提的,即sThreadLocal.get() == null。否則會拋出RuntimeException,並告訴你該線程只能創建一個Looper對象。
sThreadLocal是Looper類中定義的一個靜態ThreadLocal常量。繼續查看ThreadLocal#get()和ThreadLocal#set()方法。
#ThreadLocal.javapublic T get() { //獲取當前線程 Thread t = Thread.currentThread(); //線程中存在一個ThreadLocal.ThreadLocalMap類型的變量 //根據當前線程thread獲取到對應的ThreadLocal.ThreadLocalMap變量。 ThreadLocalMap map = getMap(t); if (map != null) { //this表示Looper類中的靜態ThreadLocal常量sThreadLocal //因爲sThreadLocal是靜態常量,作爲“key”,確保變量爲單例。 //根據sThreadLocal獲取到對應的ThreadLocalMap.Entry值。 ThreadLocalMap.Entry e = mapgetEntry(this); if (e != null) { //從ThreadLocalMap.Entry中獲取到對應的Looper, @SuppressWarnings("unchecked") T result = (T)e.value; return result; } } return setInitialValue(); }public void set(T value) { //獲取當前線程 Thread t = Thread.currentThread(); //線程中存在一個ThreadLocal.ThreadLocalMap類型的變量 //根據當前線程thread獲取到對應的ThreadLocal.ThreadLocalMap變量。 ThreadLocalMap map = getMap(t); if (map != null) //將sThreadLocal作爲“key”,Looper實例作爲“value”存儲到ThreadLocal.ThreadLocalMap中 map.set(this, value); else //創建Map並存儲值 createMap(t, value); }void createMap(Thread t, T firstValue) { //創建ThreadLocalMap,構造方法中傳入第一次存儲的鍵值對,並賦值到當前線程的threadLocals變量中。 t.threadLocals = new ThreadLocalMap(this, firstValue); }
可以觀察到,get()和set()方法獲取當前線程中的ThreadLocal.ThreadLocalMap變量。再將Looper#sThreadLocal作爲key,存儲或獲取對應的value,而value就是當前線程創建的Looper實例。
get()時是根據當前線程獲取的Looper單例,再結合Looper#prepare(boolean),可以知道單個線程只會生成Looper單個實例。
問題1:Looper如何確保線程中只有一個單例。
回答:將Looper構造方法私有化。通過Looper的靜態方法,確保只創建一次Looper對象,再將靜態常量sThreadLocal作爲key,Looper對象作爲value,存儲到當前線程的ThreadLocal.ThreadLocalMap變量中。
查看完Looper初始化的流程,再看看Looper#loop()的源碼
#Looper.javapublic static void loop() { //獲取當前線程的Looper final Looper me = myLooper(); //如果Looper沒有初始化,則拋異常 if (me == null) { throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread."); } //從Looper實例中獲取當前線程的MessageQueue final MessageQueue queue = me.mQueue; //消息循環(通過for循環) for (;;) { //1、從消息隊列中獲取消息 Message msg = queue.next(); if (msg == null) { //沒有消息表明消息隊列正在退出。 return; } //省略代碼..... //2、將Message發送給其標記的targetHandler msg.target.dispatchMessage(msg); //省略代碼..... //3、回收可繼續使用的Message msg.recycleUnchecked(); } }
Looper#loop()主要做3件事:
1、不斷從MessageQueue中取出Message,若暫無Message,則無限等待
2、將Message發送給目標Handler進行處理。
3、回收Message對象。
但發現有一種情況,當next獲取到的Message爲空時,則會退出Looper#loop()方法,即意味着消息循環結束。那什麼時候MessageQueue#next()返回null?
#MessageQueue.javaMessage next() { //如果消息循環已經退出並處理掉,請返回此處。 //如果應用程序嘗試在退出後重新啓動looper,則可能會發生這種情況。 //即MessageQueue調用了quit()方法,再次調用Looper#looper()方法時。 final long ptr = mPtr; if (ptr == 0) { return null; } //決定消息隊列中消息出隊的等待時間 or 標記爲無限等待狀態 int nextPollTimeoutMillis = 0; for (;;) { //..... // nativePollOnce方法在native層方法。 //若是nextPollTimeoutMillis爲-1,則無限等待,此時消息隊列處於等待狀態。 //若是nextPollTimeoutMillis爲0,則無需等待立即返回。 //若nextPollTimeoutMillis>0,最長阻塞nextPollTimeoutMillis毫秒(超時),如果期間有程序喚醒會立即返回。 nativePollOnce(ptr, nextPollTimeoutMillis); //嘗試檢索下一條消息。 如果找到則返回。 synchronized (this) { //獲取從開機到現在的毫秒數 final long now = SystemClock.uptimeMillis(); Message prevMsg = null; //獲取MessageQueue中的頂層Message Message msg = mMessages; //..... if (msg != null) { //如果massage的時間大於當前時間 //Message的when = Handler發送Message1時的開機時間SystemClock.uptimeMillis() + Message自身的延遲時間 if (now < msg.when) { // 下一條消息尚未就緒。 設置該Message的等待時間以在準備就緒時喚醒。 //將msg.when - now(當前開機時間) 得到該Message需要多久之後發送。 //則刷新nextPollTimeoutMillis的值,設置等待時間。 nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE); } else {//否則馬上發送Message //只有當msg.target == null時,prevMsg纔會賦值。 //遵從Handler#obtainMessage()則一般不爲空,此情況不考慮。 if (prevMsg != null) { prevMsg.next = msg.next; } else { //剛開始時prevMsg爲空 //則mMessages(頂層Message)指向當前頂層Message的下一個Message mMessages = msg.next; } //將返回的Message的下一個Message引用置空。 msg.next = null; msg.markInUse(); return msg; } } else { //如果MessageQueue中沒有Message,則會將nextPollTimeoutMillis重置爲-1,繼續等待 nextPollTimeoutMillis = -1; } //..... } //..... } }
從源碼開頭得知,當MessageQueue退出時,MessageQueue#next()則會返回Message對象爲空,從而關閉消息循環。
MessageQueue#next()主要進行等待操作和返回Message操作。而等待操作分兩種情況:
1、MessageQueue隊列中無Message,則進行無限等待操作。
2、當Message還沒到處理時間時,則計算該Message還需要等待的時間,進行相應時間的延遲。
查看Handler如何處理Message:
#Handler.javapublic void dispatchMessage(Message msg) { if (msg.callback != null) { //如果Message的callback不爲空,則將消息交由Message的callback處理 handleCallback(msg); } else { if (mCallback != null) { //如果Handler的callback不爲空,則將消息交由Handler的callback處理 if (mCallback.handleMessage(msg)) { return; } } //最後才交由Handler的handleMessage()方法處理。 handleMessage(msg); } }
Handler#dispatchMessage()主要作用時將Message分發處理。
當該Message對象的callback爲空,目標Handler的callback也爲空時,才輪到handleMessage()進行消息處理。
3.2、Message的循環再用機制
創建Message對象時,我們一般會調用Handler#obtainMessage()獲取Message對象,而不是直接new。先從Handler#obtainMessage()開始查看原由:
#Handler.javapublic final Message obtainMessage(){ return Message.obtain(this); }
#Message.java//Message鏈表,sPool是表頭private static Message sPool;//記錄當前鏈表中的數量private static int sPoolSize = 0;public static Message obtain(Handler h) { Message m = obtain(); m.target = h; return m; }public static Message obtain() { //加鎖 synchronized (sPoolSync) { if (sPool != null) { Message m = sPool; //鏈表表頭指向其下一個對象,即將表頭從鏈表中取出 sPool = m.next; //重置返回的Message的一些信息 m.next = null; m.flags = 0; // clear in-use flag //鏈表數量減一 sPoolSize--; return m; } } //如果鏈表表頭爲空,則new Message對象。 return new Message(); }
Message#obtain(Handler)調用了重載方法Message#obtain()獲取到Message對象並將Message的目標設置爲調用Handler#obtainMessage()的Message。
Message對象中擁有一個Message類型的next對象,可通過next屬性連成一個Message鏈表。Message中維繫着一個靜態Message鏈表,當鏈表不爲空時,取出表頭的Message進行返回,否則new一個Message對象。
之前查看Looper#loop()源碼時獲知,Looper#loop()最後會調用Message#recycleUnchecked(),將Message進行回收。
#Message.java//Message鏈表最大存儲數量值private static final int MAX_POOL_SIZE = 50; void recycleUnchecked() { //將消息保留在循環對象池中時將其標記爲正在使用。 //清除所有其他細節。 flags = FLAG_IN_USE; what = 0; arg1 = 0; arg2 = 0; obj = null; replyTo = null; sendingUid = -1; when = 0; target = null; callback = null; data = null; //加鎖 synchronized (sPoolSync) { //當前鏈表存儲數量小於最大值,則繼續回收 if (sPoolSize < MAX_POOL_SIZE) { //next代表的是該需要回收的Message自身的next對象 //將自身的next指向原表頭, next = sPool; //自身替換爲表頭,則通過表頭的加減實現該Message鏈表的增加和刪除。 sPool = this; //鏈表存儲數量加一 sPoolSize++; } } }
Message#recycleUnchecked()將Message的參數重置,並判斷當前Messag鏈表存儲的數量是否小於最大存儲值,若小於最大存儲值,則將該Message存儲到鏈表中,重複使用。
Message通過對鏈表表頭的增刪操作來進行鏈表的增減。
問題2:爲什麼建議使用Handler#obtainMessage()獲取Message對象,而不是直接new。
回答:Message的回收機制其實是享元設計模式的實現,Message對象存在需要反覆、較大規模創建的情況,使用享元設計模式可以減少創建對象的數量,以減少內存佔用和提高性能。
總結:
Message對象中擁有一個Message類型的next對象,可通過next屬性連成一個Message鏈表。
Message類中維繫着個靜態Message鏈表,並標記其存儲的數量值。
調用Handler#obtainMessage()或Message#obtain()方法時,嘗試從該靜態鏈表中獲取循環再用的Message對象,否則new Message對象返回出去。
當Message被Handler處理完後,Looper對象會調用Message#recycleUnchecked()將Message進行回收,並存儲到靜態Message鏈表中。
3.3、Handler兩條發送路徑:sendMessage 和 post
我們都知道,Handler可以通過sendMessage和post進行消息的發送,這兩種方法到底有什麼區別?先從sendMessage看起:
#Handler.javapublic final boolean sendMessage(Message msg){ //發送一個0延遲的message return sendMessageDelayed(msg, 0); }public final boolean sendMessageDelayed(Message msg, long delayMillis){ //延遲值不能小於0 if (delayMillis < 0) { delayMillis = 0; } //將延遲的時間和開機時間相加 return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis); }public boolean sendMessageAtTime(Message msg, long uptimeMillis) { //獲取Handler創建時存儲的當前線程的MessageQueue MessageQueue queue = mQueue; if (queue == null) { RuntimeException e = new RuntimeException( this + " sendMessageAtTime() called with no mQueue"); Log.w("Looper", e.getMessage(), e); return false; } return enqueueMessage(queue, msg, uptimeMillis); }private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) { //將Message的目標TargetHandler設置爲當前Handler //如果通過Handler#obtainMessage()獲取的Message早設置了TargetHandler爲當前Handler,一般是新new的Message才爲空。 msg.target = this; if (mAsynchronous) { msg.setAsynchronous(true); } return queue.enqueueMessage(msg, uptimeMillis); }
一路都是方法的嵌套,其中最關鍵的就是在傳遞給sendMessageAtTime()方法前,將延時時間和手機開機時間相加,得到Message對象的"執行時間"。
在繼續查看MessageQueue#enqueueMessage():
#MessageQueue.java//標記MessageQueue#next()的nativePollOnce()是否以 非零超時等待(無限等待)被阻止。private boolean mBlocked; boolean enqueueMessage(Message msg, long when) { //..... synchronized (this) { //... msg.markInUse(); //將延遲時間和開機時間相加得到的時間值存儲到message的when變量中。 msg.when = when; //獲取鏈表表頭的Message Message p = mMessages; boolean needWake; //當表頭爲空時,或者本次發送的Message對象“執行時間”比表頭的時間要小時 if (p == null || when == 0 || when < p.when) { //將本次發送的Message存儲到表頭前面,將next屬性指向原鏈表表頭 msg.next = p; //刷新MessageQueue中指向表頭的變量 mMessages = msg; needWake = mBlocked; } else { //通常不需要喚醒事件隊列,除非隊列的頭部有屏障,並且消息是隊列中最早的異步消息。 needWake = mBlocked && p.target == null && msg.isAsynchronous(); Message prev; //開啓循環,便利MessageQueue的Message鏈表 for (;;) { //prev先指向原表頭,後續循環中,不斷指向下一個元素 prev = p; //p指向下一個元素 p = p.next; //如果p== null,表示到鏈表的尾部 //或者本次發送的Message對象的“執行時間”when比下一個元素的“執行時間”要短 if (p == null || when < p.when) { //推出循環 break; } //... } //此時,prev指向的Message對象的when 比本次發送的Message對象msg的when小,即“執行時間”比它小。 //p可能爲空,即鏈表尾;或者p指向的Message對象的when比 比本次發送的Message對象msg的when大,即“執行時間”比它大。 // 即可能存在 prev.when < msg.when <p.when 或 prev.when < msg.when //將msg的next變量指向p所指的對象 msg.next = p; //prev所指向的message對象的next變量指向msg prev.next = msg; } //判斷是否需要喚醒之前在MessageQueue#next()中“陷入沉睡”的nativePollOnce()方法。 if (needWake) { nativeWake(mPtr); } } return true; }
MessageQueue#enqueueMessage()主要作用是:
1、依據msg.when的大小,按從小到大的順序,將msg插入到MessageQueue的Message鏈表中。
2、對於馬上執行的message,直接喚醒,停止nativePollOnce()的無限等待,讓MessageQueue#next返回繼續執行,從Message鏈表中取出Message,交由Looper對象進行處理。
模擬情況:
同時發送延遲400毫秒的Message對象 和 延遲300毫秒的Message對象;
100毫秒後,再發送延遲延遲250毫秒的Message對象;
情景分析:
同時發送兩個分別延遲400和延遲300的Message對象,此時系統開機時間 time = SystemClock.uptimeMillis();
延遲400的Message對象:msg400, msg400 .when = time + 400;。
首先進入MessageQueue的Message鏈表,由於原本Message鏈表爲空,p == null,表頭mMessages指 msg400
延遲300的Message對象:msg300, msg300.when = time + 300;。
進入if(p == null || when == 0 || when < p.when)語句 ,p != null ,msg300.when < msg400.when , msg300.next 指向 msg400,鏈表表頭指向msg300;
100毫秒後,發送延遲延遲250毫秒的Message對象。此時系統開機時間 time2 = SystemClock.uptimeMillis(),相對time 大了100毫秒,即time2 = time + 100毫秒。
延遲250的Message對象:msg250, msg250.when = time2 + 250, 即msg250.when = time + 350。
進入if(p == null || when == 0 || when < p.when)語句,語句不成立,進入遍歷Message鏈表的for循環。when < p.when判斷中,msg250.when > msg300.when,循環繼續。msg250.when < msg400.when,跳出循環。執行msg.next = p; 和 prev.next = msg;兩個語句,即msg250.next = msg400,msg300.next = msg250。
問題4:Looper如何管理Message隊列(即先後發送不同延遲時間的Message,Message隊列如何排序)。
回答:Message通過SystemClock.uptimeMillis() + 延遲時間給自身when賦值,通過值的大小作爲執行順序。SystemClock.uptimeMillis() 不根據當前時區的時間變化而變化,只會因開關機而被重置,否則始終自增。
所以可以根據當前的SystemClock.uptimeMillis() 與Message對象的when對比,知道馬上執行還是延遲多少秒後才執行。
轉換到Handler#ost()的源碼:
#Handler.javapublic final boolean post(Runnable r){ return sendMessageDelayed(getPostMessage(r), 0); }private static Message getPostMessage(Runnable r) { Message m = Message.obtain(); m.callback = r; return m; }public void dispatchMessage(Message msg) { if (msg.callback != null) { //如果Message的callback不爲空,則將消息交由Message的callback處理 handleCallback(msg); } else { if (mCallback != null) { //如果Handler的callback不爲空,則將消息交由Handler的callback處理 if (mCallback.handleMessage(msg)) { return; } } //最後才交由Handler的handleMessage()方法處理。 handleMessage(msg); } }private static void handleCallback(Message message) { //只是調用callback的run()方法。 message.callback.run(); }
post()傳遞的Runnable對象會被套上一層Message外殼,最後走和sendMessage()一樣的路線。
Runnable對象將存儲在Message對象的callback對象中。在Handler處理Message時,由於callback對象不爲空,調用Handler#handleCallback()對Runnable對象調用run()方法,實現Message的處理。
問題3:Handler的sendMessage() 和 post()有什麼區別。
回答:post()會將Runnable對象轉換爲Message對象,並把Runnable對象存儲在Message對象的callback中,然後繼續走sendMessage()的路線。
在Handler處理Message對象時,post()方法產生的Message對象中callback不爲空,由Handler調用Runnable對象的run方法,不會調用handleMessage();
3.4、Message的移除
#Handler.javapublic final void removeMessages(int what) { mQueue.removeMessages(this, what, null); }public final void removeCallbacks(Runnable r){ mQueue.removeMessages(this, r, null); }public final void removeMessages(int what, Object object) { mQueue.removeMessages(this, what, object); }public final void removeCallbacks(Runnable r, Object token){ mQueue.removeMessages(this, r, token); }
#MessageQueue.javavoid removeMessages(Handler h, int what, Object object) { //... synchronized (this) { //獲取Message鏈表表頭 Message p = mMessages; //從頭開始尋找,尋找第一個不符合條件的Message。分兩種情況: //1、鏈表表頭直接不符合移除條件,即第一個不符合條件的Message爲鏈表表頭,推出循環。 //2、鏈表符合移除條件,將鏈表表頭指向原表頭的下一個Message,並回收原鏈表表頭。新的鏈表表頭繼續進行判斷,直到出現不符合移除條件的Message出現。 //最後鏈表表頭mMessages 和 p都指向第一個不符合條件的Message,前面符合移除條件的Message已被移除。 while (p != null && p.target == h && p.what == what && (object == null || p.obj == object)) { Message n = p.next; mMessages = n; p.recycleUnchecked(); p = n; } //從第一個不符合條件的Message對象開始,迭代尋找其下一個Message是否符合移除條件。 while (p != null) { Message n = p.next; if (n != null) { //判斷是否符合移除條件 if (n.target == h && n.what == what && (object == null || n.obj == object)) { //獲取p.next().next()的Message對象,即下下個對象。 Message nn = n.next; //符合條件的回收 n.recycleUnchecked(); //將原本的下下個Message轉移到next對象中,即轉移到下一個Message的位置上。 p.next = nn; continue; } } //n == null,表示到鏈尾了,則 p == null,while循環結束。 p = n; } } } void removeMessages(Handler h, Runnable r, Object object) { if (h == null || r == null) { return; } synchronized (this) { Message p = mMessages; // Remove all messages at front. while (p != null && p.target == h && p.callback == r && (object == null || p.obj == object)) { Message n = p.next; mMessages = n; p.recycleUnchecked(); p = n; } // Remove all messages after front. while (p != null) { Message n = p.next; if (n != null) { if (n.target == h && n.callback == r && (object == null || n.obj == object)) { Message nn = n.next; n.recycleUnchecked(); p.next = nn; continue; } } p = n; } } }
removeMessages(Handler, **int**, Object) 根據Message中的**what**進行刷選移除對象。 removeMessages(Handler, **Runnable**,Object)則根據相同的**Runnable**對象進行刷選移除。 兩者的都是走相同的移除對象流程,只是其中的一種刷選條件有所不同,what針對的是Handler#sendMessage()發送的Message,Runnable針對的是Handler#post()發送的Message。 Handler#removeCallbacksAndMessages()則移除這兩種刷選條件,針對所有Message。
問題5:removeCallbacks、removeMessages 和 removeCallbacksAndMessages都移除了什麼
回答:removeCallbacks、removeMessages 和 removeCallbacksAndMessages 在待處理的Message鏈表中,根據各自的刷選條件尋找符合移除條件的對象,將符合條件的Message移除出Message鏈表,並回收該Message。
四、總結
Message對象中擁有一個Message類型的next對象,可通過next屬性連成一個Message鏈表。
Message類中維繫着個靜態Message鏈表,存儲着回收的Message對象,等待重複使用。
MessageQueue類中也維繫着個靜態Message鏈表,存儲着待處理的Message的對象,等待MessageQueue#next()方法將其取出,交由目標Handler處理。
當用戶調用Handler#obtainMessage()時,嘗試從該Message鏈表中獲取待循環再用的Message,獲取失敗則new一個新的Message對象。
當Message被目標Handler處理完成後,會被回收到Message類的靜態Message鏈表中。
當調用Handler一系列remove方法後,被移除的Message會被回收到Message類的靜態Message鏈表中。post方法發送的Runnable對象將會被包裝成一個Message走sendMessage路線,Runnable對象被存儲在Message的callback變量中。
當該Message對象的callback爲空,目標Handler的callback也爲空時,纔將Message交由handleMessage()進行處理。即post方法產生的Message對象會被交由Handler#handleCallback()直接調用run方法,不走Handler#handleMessage()。
msg.when = 延時時間 + 手機開機時間。再依據msg.when的大小,按從小到大的順序,將msg插入到MessageQueue的Message鏈表中。
Looper類中的靜態ThreadLocal常量作爲key,當前線程的Looper對象做爲value,存儲在當前線程的ThreadLocal.ThreadLocalMap變量。ThreadLocal常量確保key唯一,也就確保value唯一,並且Looper#prepare()只允許創建一遍Looper對象。
handler
關於Android進階的全部學習內容,我們這邊都有系統的知識體系以及進階視頻資料,有需要的朋友可以加羣免費領取安卓進階視頻教程,源碼,面試資料,羣內有大牛一起交流討論技術;818520403(包括自定義控件、NDK、架構設計、混合式開發工程師(React native,Weex)、性能優化、完整商業項目開發等)
Android高級進階視頻教程