簡介
Android線程爲了隨時接收消失處理,需要一套消息處理機制。應用程序通過消息驅動應用程序運行。
相關類 | 簡介 |
---|---|
Thread | 消息隊列需要在線程裏面創建,並且在線程結束的問題循環接受消息 |
Looper | 消息泵,負責循環穿件消息隊列,接受消息,分發消息 |
Handler | 負責發送消息和接受消息 |
MessageQueue | 消息隊列,消息發送後會在消息隊列裏等待消息泵處理 |
Message | 具體的消息.被消息泵分發,被handler接受,被消息隊列運輸 |
Callback | Handler處理消息的一個接口 |
android消息機制主要流程
- App進程創建
- 初始化一個消息隊列
- 主線程死循環讀取消息隊列
Android應用主線程通過創建消息隊列,然後在無限循環中等待或獲取消息隊列傳遞的信息,然後處理。上面是主線程的消息機制流程,android允許子線程創建自己的消息循環.
相關類:MessageQueue,Looper,Handler
主線程的消息隊列在系統創建應用程序的時候就進行了主線程的消息循環機制的配置。
frameworks/base/core/java/android/app/ActivityThread.java
public final class ActivityThread extends ClientTransactionHandler {
public static void main(String[] args) {
....
Looper.prepareMainLooper();
...
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
如果是子線程Looper.prepareMainLooper()換成Looper.prepare()
frameworks/base/core/java/android/os/Looper.java
public final class Looper {
public static void prepareMainLooper() {//1
prepare(false);
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
sMainLooper = myLooper();
}
}
public static void prepare() {//2
prepare(true);
}
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
private Looper(boolean quitAllowed) {//3
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
public void quit() {//4
mQueue.quit(false);
}
}
frameworks/base/core/java/android/os/MessageQueue.java
void quit(boolean safe) {
if (!mQuitAllowed) {
throw new IllegalStateException("Main thread not allowed to quit.");//5
}
......
}
上面的操作主要是配置初始化。主線程Looper.prepareMainLooper(),子線程Looper.prepare(),之所以主線程用了不同的方法,是因爲主線程的消息機制不能停止,而子線程是用戶自己創建的是可以停止.代碼差異在於3處,當MessageQueue的參數是false時,當嘗試結束Looper調用quit方法時,會報" throw new IllegalStateException(“Main thread not allowed to quit.”)",
有了消息隊列,還有消息循環。通過循環獲取消息池的信息,驅動程序。
當我們調用 Looper.loop();
/**
* Run the message queue in this thread. Be sure to call
* {@link #quit()} to end the loop.
*/
public static void loop() {
...
for (;;) {//1
Message msg = queue.next(); // might block //2
...
msg.target.dispatchMessage(msg);//3
...
}
}
1處是個無限循環,2處獲取消息隊列中的消息,然後分發給對應的handler