盒子
盒子
文章目录
  1. 一、一个线程中只有一个 Looper
  2. 二、一个 Looper 内部维护了一个 MessageQueue 消息队列
  3. Handler 负责发送 Message 消息到与之绑定的线程中 Looper 中的 MessageQueue
  4. 三、Looper 的作用就是循环取出 MessageQueue 中的 Message 并返交给发送它的 Handler 去处理
  5. 四、一个线程中可以有多个 Handler,但一个 Handler 只能与一个 Looper 绑定

Android 消息循环机制总结

要想在一个线程要想使用消息循环系统,通常需要:

1
2
3
Looper.prepare();
mHandler = new Handler() {...};
Looper.loop();

而在 UI 线程直接创建 Handler 实例就可以直接使用(通过Handler 的无参构造函数创建的 Handler 默认与当前线程的 Looper 绑定),是因为在 ActivityThread 中的 main() 方法中,系统已为我们自动创建好了 Looper 并调用了 loop() 方法开启了循环:

1
2
3
4
5
6
7
public static void main(String[] args) {
...
Looper.prepareMainLooper();
...
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}

Looper.prepareMainLooper(); 实际上就是调用了 Looper 的 prepare() 方法,之所以系统弄了一个 prepareMainLooper()方法是因为系统在给 UI 线程创建 Looper 实例的时候顺便把这个实例赋值给了 Looper 的一个内部静态变量 sMainLooper:

1
private static Looper sMainLooper;

并且提供了一个静态方法 getMainLooper() 供外部调用来获取这个 sMainLooper,方便在其他线程中可随时拿到 UI 线程的 Looper,一旦拿到 UI 线程的 Looper,我们就可以在其他线程很方便地创建一个与 UI 线程中的 Looper 相关联的 Handler 了,例如下面这样:

1
Handler handler = new Handler(Looper.getMainLooper){...};

一、一个线程中只有一个 Looper

1
2
3
4
5
6
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));
}

二、一个 Looper 内部维护了一个 MessageQueue 消息队列

1
2
3
4
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}

Handler 负责发送 Message 消息到与之绑定的线程中 Looper 中的 MessageQueue

Handler 的各种 sendMessage() 方法最后都会辗转来到 Handler 的 enqueueMessage() 方法,在内部调用了与 Handler 相绑定线程的 Looper 内部的 MessageQueue 的 enqueueMessage() 来将消息放进消息队列中。

1
2
3
4
5
6
7
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}

三、Looper 的作用就是循环取出 MessageQueue 中的 Message 并返交给发送它的 Handler 去处理

Looper.loop() 调用后即开启了循环系统:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public static void loop() {
...
for (;;) {
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
...
try {
msg.target.dispatchMessage(msg);
} finally {
if (traceTag != 0) {
Trace.traceEnd(traceTag);
}
}
...
}
}

Looper 不断的从 MessageQueue 队列中取出消息并调用了消息的 target.dispatchMessage(msg) 方法,Message 的 target 一般为发送消息的 Handler (上面 Handler enqueueMessage()的代码块中有体现 msg.target = this ),Handler 的 dispatchMessage() 方法就是对消息的处理了,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
* Handle system messages here.
*/
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
1
2
3
private static void handleCallback(Message message) {
message.callback.run();
}

可以看到,会优先把消息交给 Message 的 callback (一个 Runnable) 的 run() 方法处理,如果 callback 为空就会再尝试给 Handler 的 callback(mCallback) 处理,如果 Handler 的 callback 也为空,就会给 Handler 我们熟知的 handleMessage() 方法处理。

四、一个线程中可以有多个 Handler,但一个 Handler 只能与一个 Looper 绑定

赞赏
扫一扫,支持 Melody
  • 微信二维码
  • 支付宝二维码