Android非同步訊息處理機制原始碼分析
宣告:本文是參考了以下幾位大神的文章,自己按照自己的思維習慣整理的筆記,並新增一些相關的內容。如有不正確的地方歡迎留言指出,謝謝!
郭霖部落格
鴻洋部落格
任玉剛《Android開發藝術探索》
一. Andoid訊息機制概述
Android規定訪問UI只能在主執行緒進行,如果在子執行緒中訪問UI,那麼程式就會丟擲異常。ViewRootImpl對UI操作做了驗證,這個驗證工作是由ViewRootImpl的checkThread方法來完成的,如下:
void checkThread(){
if(mThread != Thread.currentThread()){//不是主執行緒,丟擲異常
throw new CalledFromWrongThreadException("Only the
original thread that created a view hierarchy can touch its views);
}
}
Android為什麼不允許在子執行緒中訪問UI呢?
因為Android的UI控制元件不是執行緒安全的,如果在多執行緒中併發訪問可能會導致UI控制元件處於不可預期的狀態。
為什麼系統不對UI控制元件的訪問加上鎖機制?
1. 首先加上鎖機制會讓UI訪問的邏輯變得複雜
2. 鎖機制會降低UI訪問的效率,因為鎖機制會阻塞某些執行緒的執行
回想一下,實際開發中,在子執行緒進行UI操作,通常有以下幾種方法:
- 呼叫 runOnUiThread() 方法,通過匿名內部類實現run()方法進行UI操作
- 使用AsyncTask
- 在主執行緒中建立Handler物件,子執行緒建立Message物件,然後通過 sendMessage() 傳送建立的Message,主執行緒通過handleMessage() 處理接收到的Message
- Handler的 post() 方法
- View的 post() 方法
其實,這麼多的方法,其內部的實現原理都是一樣的,都是通過接下來我們要說的Android非同步訊息處理機制來實現的。
二. Android非同步訊息處理機制分析
Android的非同步訊息處理機制實際上就是Handle的執行機制,因此本節主要圍繞Handler的工作過程來分析,主要包括 Handler 、Message 、MessageQueue 和 Looper 這四個類。另外,為了更好地理解Looper這個類,還會介紹 ThreadLocal 這個類。
1. ThreadLocal的工作原理
ThreadLocal是一個執行緒內部的 資料儲存類,通過它可以在指定的執行緒中儲存資料,資料儲存後,只有在指定執行緒中可以獲取到儲存的資料,對於其他執行緒來說則無法獲取到資料。
ThreadLocal的使用場景:
- 當某些資料是以執行緒為作用域並且不同執行緒具有不同的資料副本的時候
- 複雜邏輯下的物件傳遞。比如監聽器的傳遞,有時候一個執行緒中的任務過於複雜,這可能表現為函式呼叫棧比較深以及程式碼入口的多樣性,在這種情況下,我們又需要監聽器能夠貫穿整個執行緒的執行過程,就可以採用ThreadLocal,讓監聽器作為執行緒內部的全域性物件而存在,線上程內部只要通過get方法就可以獲取到監聽器。
下邊通過例子看一下ThreadLocal的真正含義:
//定義一個ThreadLocal物件,儲存一個Boolean型別的資料
ThreadLocal<Boolean> mBooleanThreadLocal = new ThreadLocal<Boolean>();
//在主執行緒中設定值為true
mBooleanThreadLocal.set(true);
System.out.println("[Thread#main]mBooleanThreadLocal=" + mBooleanThreadLocal.get());
//新建子執行緒1,設定值為false
new Thread("Thread#1"){
@Override
public void run() {
mBooleanThreadLocal.set(false);
System.out.println("[Thread#1]mBooleanThreadLocal=" + mBooleanThreadLocal.get());
};
}.start();
//新建子執行緒2,不設定
new Thread("Thread#2"){
@Override
public void run() {
System.out.println("[Thread#1]mBooleanThreadLocal=" + mBooleanThreadLocal.get());
};
}.start();
上面程式碼中,在主執行緒中設定mBooleanThreadLocal的值為true,在子執行緒1中設定其值為false,在子執行緒2不設定其值。然後分別在3個執行緒中通過get方法獲取mBooleanThreadLocal的值,根據前邊對ThreadLocal的描述,這個時候,主執行緒應該是true,子執行緒1中應該是false,而子執行緒2中由於沒有設定值,所以應該是null。執行結果如下:
[Thread#main]mBooleanThreadLocal=true
[Thread#1]mBooleanThreadLocal=false
[Thread#1]mBooleanThreadLocal=null
從執行結果可以看出,雖然在不同執行緒中訪問的是同一個ThreadLocal物件,但是它們通過ThreadLocal獲取的值卻不一樣,這就是ThreadLocal的奇妙之處。
ThreadLocal之所以有這麼奇妙的效果,是因為不同執行緒訪問同一個ThreadLocal的get方法,ThreadLocal內部會從各自執行緒中取出一個數組,然後再從陣列中根據當前ThreadLocal的索引去查找出對應的value值。很顯然,不同執行緒中的陣列是不同的。
2. MessageQueue的工作原理
MessageQueue主要包含兩個操作:插入和讀取
。對應的方法為 enqueueMessage() 和 next(),其中enqueueMessage的作用就是往訊息佇列插入一條訊息,而next的作用是從訊息佇列中取出一條訊息並將其從訊息佇列刪除。故讀取操作本身會伴隨著刪除操作。
儘管MessageQueue叫訊息佇列,當時它的內部實現並不是用的佇列,實際上它是通過一個單鏈表的資料結構來維護訊息列表,單鏈表在插入和刪除上比較有優勢。
enqueueMessage的原始碼如下:
final boolean enqueueMessage(Message msg, long when) {
if (msg.when != 0) {
throw new AndroidRuntimeException(msg + " This message is already in use.");
}
if (msg.target == null && !mQuitAllowed) {
throw new RuntimeException("Main thread not allowed to quit");
}
synchronized (this) {
if (mQuiting) {
RuntimeException e = new RuntimeException(msg.target + " sending message to a Handler on a dead thread");
Log.w("MessageQueue", e.getMessage(), e);
return false;
} else if (msg.target == null) {
mQuiting = true;
}
msg.when = when;
Message p = mMessages;
if (p == null || when == 0 || when < p.when) {
msg.next = p;
mMessages = msg;
this.notify();
} else {
Message prev = null;
while (p != null && p.when <= when) {
prev = p;
p = p.next;
}
msg.next = prev.next;
prev.next = msg;
this.notify();
}
}
return true;
}
觀察上面的程式碼,可以發現,其實所謂的入隊其實是將所有的訊息按時間進行排序(通過比較when引數)。具體的操作方法就是根據時間順序呼叫msg.next(),從而為每一個訊息指定它的下個訊息是什麼。
next()方法有點長,這裡不貼出來。next()方法是一個無限迴圈方法,如果訊息佇列中沒有訊息,那麼next方法就會一直阻塞。當有新訊息到來時,next方法會返回這條訊息並將其從單鏈表移除。
3. Looper的工作原理
Looper在Android訊息機制中扮演著訊息迴圈的角色,負責建立一個MessageQueue,然後進入一個死迴圈不斷從該MessageQueue中讀取訊息。Looper主要有兩個方法,prepare() 和 looper()。
首先看prepare()的原始碼:
public static final void prepare() {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(true));
}
可以看到,首先判斷sThreadLocal中是否已經存在Looper了,如果還沒有則建立一個新的Looper設定進去。如果sThreadLocal已經有了looper,則丟擲異常,這也說明Looper.prepare()不能被呼叫兩次,同時保證了一個執行緒中只有一個Looper例項
。
再來看看Looper的構造方法:
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mRun = true;
mThread = Thread.currentThread();
}
在Looper的構造方法中,建立了一個MessageQueue。由於Looper只能被呼叫一次,這也就保證了一個執行緒只能有一個Looper例項,一個Looper只能對應一個MessageQueue。
Looper最重要的方法是looper方法,只有呼叫了looper後,訊息系統才會真正地起作用。下面看看loop()原始碼:
public static final void loop() {
final Looper me = myLooper();
if(me == null){
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
final MessageQueue queue = me.mQueue;
for(;;) {//死迴圈
Message msg = queue.next(); // might block(可能阻塞)
if (msg != null) {
if (msg.target == null) {
return;
}
if (me.mLogging!= null) me.mLogging.println(
">>>>> Dispatching to " + msg.target + " "
+ msg.callback + ": " + msg.what
);
//把訊息交給msg的target的dispatchMessage方法去處理。
msg.target.dispatchMessage(msg);
if (me.mLogging!= null) me.mLogging.println(
"<<<<< Finished to " + msg.target + " "
+ msg.callback);
//釋放訊息佔用資源
msg.recycle();
}
}
}
looper()方法會陷入一個死迴圈,不斷地呼叫MessageQueue的 next() 方法去獲取訊息佇列中的訊息。每當有一個訊息出隊,就將它傳遞到 msg.target
的 dispatchMessage() 方法,這裡的msg.target就是Handler。如果訊息佇列為空,則會阻塞
。
另外,看看myLooper方法
public static final Looper myLooper() {
return (Looper)sThreadLocal.get();
}
在looper()方法中,會先呼叫myLooper()方法判斷looper是否為空。故,looper()必須在呼叫prepare()後才能呼叫。
Looper提供了quit 和 quitSafely來退出一個Looper,二者區別是:quit會直接退出,而quitSafely只是設定一個退出標記,然後把訊息佇列中的已有訊息處理完畢後才安全退出。
public void quit() {
mQueue.quit(false);
}
public void quitSafely() {
mQueue.quit(true);
}
從原始碼可以看到,退出Looper的兩個方法都呼叫了MessageQueue的quit()方法。
void quit(boolean safe) {
...
synchronized (this) {
if (mQuitting) {
return;
}
mQuitting = true;
if (safe) {
removeAllFutureMessagesLocked();
} else {
removeAllMessagesLocked();
}
...
}
}
通過原始碼,發現,最終,分別呼叫的是MessageQueue的 removeAllFutureMessagesLocked()
和 removeAllMessagesLocked()
方法。removeAllMessagesLocked()方法主要是把MessageQueue訊息池中所有的訊息全部清空,無論是延遲訊息還是非延遲訊息;而removeAllFutureMessagesLocked()方法只會清空MessageQueue訊息池中所有的延遲訊息,並將訊息池中所有非延遲訊息派發出去讓Handler去處理完後才停止Looper迴圈。quitSafely相比於quit方法安全的原因在於清空訊息之前會派發所有的非延遲訊息。
在子執行緒中,如果手動為其建立了Looper,那麼在所有的事情處理完成後應該呼叫quit方法來終止訊息迴圈,否則這個子執行緒就會一直處於等待狀態。
4. Handler的工作原理
Handler 的工作主要包含訊息的傳送和接收過程。訊息的傳送可以通過 post() 的一系列方法以及 send() 的一系列方法來實現。使用Handler之前,我們都是初始化一個例項,所以想來看看Handle的構造方法,看其如何與MessageQueue聯絡上的,它在子執行緒中傳送的訊息(一般傳送訊息都在非UI執行緒)怎麼傳送到MessageQueue中的。
Handler的無參構造方法:
public Handler() {
if (FIND_POTENTIAL_LEAKS) {
final Class<? extends Handler> klass = getClass();
if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
(klass.getModifiers() & Modifier.STATIC) == 0) {
Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
klass.getCanonicalName());
}
}
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
mCallback = null;
}
可以看到,構造方法中會呼叫Looper.myLooper()來獲取當前的Looper物件,如果Looper為空,則會丟擲異常。然後又獲取了這個Looper例項中儲存的MessageQueue(訊息佇列),這樣就保證了handler的例項與我們Looper例項中MessageQueue關聯上了。
然後看看我們最常用的 sendMessage() 方法:
public final boolean sendMessage(Message msg){
return sendMessageDelayed(msg, 0);
}
public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {
Message msg = Message.obtain();
msg.what = what;
return sendMessageDelayed(msg, delayMillis);
}
public final boolean sendMessageDelayed(Message msg, long delayMillis) {
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
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);
}
輾轉發側,最後呼叫了 sendMessageAtTime() 。其實,Handler有很多傳送訊息的方法,其中除了sendMessageAtFrontOfQueue()方法之外,其它的傳送訊息方法最終都會輾轉呼叫到sendMessageAtTime()方法中。
sendMessageAtTime()方法接收兩個引數,其中msg引數就是我們傳送的Message物件,而uptimeMillis引數則表示傳送訊息的時間,它的值等於自系統開機到當前時間的毫秒數再加上延遲時間。
sendMessageAtTime()方法又呼叫了enqueueMessage()方法:
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
這個方法中首先為 msg.target 賦值為this,也就是把當前的handler作為msg的target屬性,最終會呼叫queue的enqueueMessage()方法入佇列。如果大家還記得Looper的looper()方法,該方法中會取出每一個msg,然後交給msg.target.dispatchMessage(msg)
通過處理訊息,上文說這裡的msg.target就是一個Handler物件就是在這裡注入的。
接下來看看dispatchMessage()方法:
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
該方法中,先進行判斷,如果mCallback不為空,則呼叫mCallback的handleMessage()方法,否則直接呼叫Handler的handleMessage()方法。而Handler的handleMessage是一個空方法,所以一般我們會繼承Handler並重寫handlerMessage()方法來實現我們處理訊息的邏輯。
5. 總結
一個最標準的非同步訊息處理執行緒應該是這樣寫的:
class LooperThread extends Thread {
public Handler mHandler;
public void run() {
Looper.prepare();
mHandler = new Handler() {
public void handleMessage(Message msg) {
// process incoming messages here
}
};
Looper.loop();
}
}
分析一下,為什麼使用非同步訊息處理的方式就可以對UI進行操作了呢?這是由於Handler總是依附於建立時所在的執行緒,比如我們的Handler是在主執行緒中建立的,而在子執行緒中又無法直接對UI進行操作,於是我們就通過一系列的傳送訊息、入隊、出隊等環節,最後呼叫到了Handler的handleMessage()方法中,這時的handleMessage()方法已經是在主執行緒中執行的,因而我們當然可以在這裡進行UI操作了。整個非同步訊息處理流程的示意圖如下圖所示:
總結一下:
1. 首先Looper.prepare()在本執行緒中儲存一個Looper例項,然後該例項中儲存一個MessageQueue物件;因為Looper.prepare()在一個執行緒中只能呼叫一次,一個執行緒只會有一個Looper和一個MessageQueue
2. Looper.loop()會讓當前執行緒進入一個無限迴圈,不斷從MessageQueue佇列中通過next()方法獲取訊息,然後回撥msg.target.dispatchMessage(msg)方法進行處理
3. Handler的構造方法,會首先得到當前執行緒中儲存的Looper例項,進而與Looper例項中的MessageQueue進行關聯
4. Handler的sendMessage()方法,會給msg的target賦值為handler自身,然後加入MessageQueue中
5. 在構造Handler例項時,我們會重寫handleMessage()方法,也就是msg.target.dispatchMessage(msg)最終呼叫的方法
三. 子執行緒進行UI操作幾種方式的分析
本文開始的時候就歸納了5種在子執行緒中進行UI操作的方法,前邊分析了整個Android非同步訊息處理機制的流程,也就是我們比較常用的通過重寫Handler的handleMessage()方法這一流程。下邊,我們對其它幾種方式進行分析。
1. Handler的post()方法
Handler的post()方法如下:
public final boolean post(Runnable r){
return sendMessageDelayed(getPostMessage(r), 0);
}
呼叫了sendMessageDelayed()方法去傳送一條訊息,並且還使用了getPostMessage()方法將Runnable物件轉換成Message。
private final Message getPostMessage(Runnable r) {
Message m = Message.obtain();
m.callback = r;
return m;
}
這個方法中,將訊息的callback欄位值指定為傳入的Runnable物件。在Handler的dispatchMessage()方法中原來有做一個檢查,如果Message的callback等於null才會去呼叫handleMessage()方法,否則就呼叫handleCallback()方法。那我們快來看下handleCallback()方法中的程式碼吧:
private final void handleCallback(Message message) {
message.callback.run();
}
非常粗暴,直接呼叫一開始傳入的Runnable物件的run()方法。因此,在子執行緒中通過Handler的post()方法進行UI操作可以這麼寫:
public class MainActivity extends Activity {
private Handler handler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
handler = new Handler();
new Thread(new Runnable() {
@Override
public void run() {
handler.post(new Runnable() {
@Override
public void run() {
// 在這裡進行UI操作
}
});
}
}).start();
}
}
2. View的post()方法
看一下View中的post()原始碼:
public boolean post(Runnable action) {
Handler handler;
if (mAttachInfo != null) {
handler = mAttachInfo.mHandler;
} else {
ViewRoot.getRunQueue().post(action);
return true;
}
return handler.post(action);
}
直接呼叫了上邊分析過的Handler的post()方法
3. Activity的runOnUiThread()方法
public final void runOnUiThread(Runnable action) {
if (Thread.currentThread() != mUiThread) {
mHandler.post(action);
} else {
action.run();
}
}
也很簡單,先判斷當前執行緒是不是主執行緒,如果不是,呼叫handler的post()方法。否則直接呼叫Runnable的run()方法。
4. AsyncTask機制
由於AsyncTask後邊會專門寫一篇文章介紹,這裡就不展開了。
相關推薦
Android非同步訊息處理機制原始碼分析
宣告:本文是參考了以下幾位大神的文章,自己按照自己的思維習慣整理的筆記,並新增一些相關的內容。如有不正確的地方歡迎留言指出,謝謝! 郭霖部落格 鴻洋部落格 任玉剛《Android開發藝術探索》 一. Andoid訊息機制概述
Android非同步訊息處理機制詳解及原始碼分析
PS一句:最終還是選擇CSDN來整理髮表這幾年的知識點,該文章平行遷移到CSDN。因為CSDN也支援MarkDown語法了,牛逼啊! 【工匠若水 http://blog.csdn.net/yanbober 轉載煩請註明出處,尊重分享成果】 最近相對來說比較閒,加上養病,所
Android非同步訊息處理機制的原始碼分析
1、背景 相信做過一段時間的Android開發都瞭解,當我們在子執行緒中更新UI時會丟擲異常,導致程式崩潰,Android4.0之後只允許在UI執行緒中更新介面,但是我們也不能再UI執行緒中處理耗時操作,那樣會導致應用程式無響應(即出現ANR)。 那如果想解
android 非同步訊息處理機制 — AHandler
1. 引入 ALooper、AHandler、AMessage 在 android multimedia stagefright 的框架程式碼中,通篇都是這幾個類的身影,所以熟悉 android 多媒體框架的第一步必須理解這幾個類的含義。 這幾個類是為了實現非同步訊息機制而設計的
Android非同步訊息處理機制:Looper、Handler、Message
1 簡介 Handler,Looper,Message這三者都與Android非同步訊息處理執行緒相關, Looper:負責建立一個MessageQueue,然後進入一個無限迴圈體不斷從該MessageQueue中讀取訊息; Handler:訊息建立者,一個或者多個
(轉載)Android 非同步訊息處理機制 讓你深入理解 Looper、Handler、Message三者關係
很多人面試肯定都被問到過,請問Android中的Looper , Handler , Message有什麼關係?本篇部落格目的首先為大家從原始碼角度介紹3者關係,然後給出一個容易記憶的結論。 1、 概述 Handler 、 Looper 、Message
深入理解Android非同步訊息處理機制
一。概述 Android 中的非同步訊息處理主要分為四個部分組成,Message、Hndler、MessageQueue 和 Looper。其關係如下圖所示: 1. Message 是執行緒之間傳遞的訊息,它可以在內部攜帶少量資訊,用於在不同執行緒之間交換資料。 2. Messag
android非同步訊息處理機制
android非同步訊息處理主要由四部分組成:Handler,Looper,Message,MessageQueue Message:執行緒之間傳遞的訊息,可以在內部攜帶少量訊息 MessageQueue: Looper:每個執行緒有且最多隻能有一個Looper物件
Android非同步訊息處理機制 handler
我們都知道,Android UI是執行緒不安全的,如果在子執行緒中嘗試進行UI操作,程式就有可能會崩潰。相信大家在日常的工作當中都會經常遇到這個問題,解決的方案應該也是早已爛熟於心,即建立一個Message物件,然後藉助Handler傳送出去,之後在Handler的han
Android 非同步訊息處理機制解析
一、Message、Handler、MessageQueue、Looper Android 中的非同步訊息處理主要由四個部分組成,Message、Handler、MessageQueue、Looper。 1. Message: Message 是線上
Android 非同步訊息處理機制 讓你深入理解 Looper、Handler、Message三者關係
很多人面試肯定都被問到過,請問Android中的Looper , Handler , Message有什麼關係?本篇部落格目的首先為大家從原始碼角度介紹3者關係,然後給出一個容易記憶的結論。1、 概述Handler 、 Looper 、Message 這三者都與Android
Android非同步訊息處理機制學習筆記
(一)Handler 什麼是Handler Android訊息機制的上層介面,Handler通過傳送和處理Message和Runnable物件來關聯相對應執行緒的MessageQueeu. 可
Android非同步訊息處理機制詳解
關於Handler例項化的一些關鍵資訊,具體如下: 在主執行緒中可以直接建立Handler物件,而在子執行緒中需要先呼叫Looper.prepare()才能建立Handler物件,否則執行丟擲”
Android非同步訊息處理機制Handler
很多人第一次接觸Handler可能是因為一句話”子執行緒不能操作ui”,那子執行緒能不能操作ui呢?我們在這裡不多討論(其實是可以的,但是執行緒不安全),我們來分析下handler是如何運轉起來的。 一般用法都是在“主執行緒”中new一個handler
Handler非同步訊息處理機制的原始碼分析
1. Handler非同步訊息處理機制 主執行緒不能進行耗時操作 (會發生ANR異常) 子執行緒不能更新UI的操作 (因為會報異常——>只有產生該控制元件的執行緒才能操作該控制元件。) 那麼 , 要在子執行緒請求資料,然後將資料傳送到主執行緒中更新
android的訊息處理機制——Looper,Handler,Message (原理圖、原始碼)
轉自:http://my.oschina.net/u/1391648/blog/282892 在開始討論android的訊息處理機制前,先來談談一些基本相關的術語。 通訊的同步(Synchronous):指向客戶端傳送請求後,必須要在服務端有迴應後客戶端才繼續傳送
Android Handler 非同步訊息處理機制的妙用 建立強大的圖片載入類
最近建立了一個群,方便大家交流,群號:55032675上一篇部落格介紹了Android非同步訊息處理機制,如果你還不瞭解,可以看:Android 非同步訊息處理機制 讓你深入理解 Looper、Handler、Message三者關係 。那篇部落格的最後,提出可以把非同步訊息處理
Android的訊息處理機制:Message、Handlerhe和Looper原始碼解析
android的訊息處理有三個核心類:Looper,Handler和Message。其實還有一個Message Queue(訊息佇列),但是MQ被封裝到Looper裡面了,我們不會直接與MQ打交道,因此我沒將其作為核心類。下面一一介紹: 執行緒的魔法師 Looper Loo
Android中的非同步訊息處理機制
這也是Android中老生常談的一個話題了,它本身並不是很複雜,可是面試官比較喜歡問。本文就從原始碼再簡單的理一下這個機制。也可以說是理一下Handler、Looper、MessageQueue之間的關係。 單執行緒中的訊息處理機制的實現 首先我們以Looper.java原始碼中給出的一個例子來