Android 异步消息机制 Handler、Message、Looper
此文为鸿洋博客阅读笔记,配合原文食用口味更佳。
Android 异步消息处理机制 让你深入理解 Looper、Handler、Message 三者关系 - CSDN 博客
导图
过程分析
Looper
Looper.perpare()
Looper.perpare()
方法创建Looper对象
(同时创建MessageQueue对象
),并与当前线程关联保存在sThreadLocal
中。
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));
}
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mRun = true;
mThread = Thread.currentThread();
}
Looper.loop()
Looper.loop()
方法获取保存的Looper对象
并由此获取到MessageQueue对象
。
通过for循环
,不停的通过mQueue
获取到msg
,并调用msg.target.dispatchMessage(msg)
执行 msg 对应的处理方法。
最后通过msg.recycle()
回收使用完的 msg。
public static void loop() {
final Looper me = myLooper();
...
final MessageQueue queue = me.mQueue;
...
for (;;) {
Message msg = queue.next(); // might block
...
msg.target.dispatchMessage(msg);
...
msg.recycle();
}
}
Looper.myLooper()
myLooper()
内部调用sThreadLocal
获取已有的Looper对象
public static Looper myLooper() {
return sThreadLocal.get();
}
Android 的 Activity 默认在 UI 线程调用了 Looper 的prepare()
和loop()
方法
Handler
handler.sendMessage()
Handler 构造方法会获取到mLooper
和mQueue
以及mCallback
mLooper = Looper.myLooper();
mQueue = mLooper.mQueue;
mCallback = callback; // Handler() 中此值为 null
sendMessage()
方法最终会调用sendMessageAtTime()
方法,在其内部调用enqueueMessage()
方法,将 handler 赋予 msg.target,并将 msg 压入 mQueue 中
//enqueueMessage 方法
msg.target = this;
queue.enqueueMessage(msg, uptimeMillis);//将 handler 发送的 msg 压入到当前线程的 Looper 持有的 MessageQueue 中
handler.dispatchMessage()
Handler 的dispatchMessage()
方法会在Looper.loop()
中被调用
public void dispatchMessage(Message msg) {
if (msg.callback != null) { //msg 自带的回调方法
handleCallback(msg);
} else {
if (mCallback != null) { //handler 指定的回调方法
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg); //handler 的 handleMessage() 方法
}
}
其中执行顺序是:msg.callback
> mCallback
> handleMessage()
handler.post()
handler.post(new Runnable())
调用了getPostMessage(r)
方法将 r 赋予 msg.callback
public 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;
}
最后也是在sendMessageDelayed方法
中调用sendMessageAtTime()方法
将 msg 压入 MessageQueue 中
public final boolean sendMessageDelayed(Message msg, long delayMillis) {
...
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
msg 的获取
Message.obtain();
复用 MessageMessage 池中已有的对象,避免出现分配内存 推荐new Message();
总结
Looper在**perfare()
**方法中创建Looper及MessageQueue对象
并保存在sThreadLocal
中,
在**loop()
**方法中通过myLooper()
从sThreadLocal
中取出mLooper
,并由此获得mQueue
,在 for 循环中通过mQueue.next()
获取msg
,用msg.target.dispatchMessage()
方法回调handler中的msg处理方法
。
Handler在**构造函数
**中通过Looper.myLooper()
获取到当前线程的Looper和MessageQueue
;
**sendMessage()
**方法最终通过sendMessageAtTime()
调用enqueueMessage()
方法将msg压入到MessageQueue
中。
至此将Looper 和 Handler 通过 MessageQueue 联系在一起,并共同参与处理 Message。
此外**handler.post(runnable)
也是通过在post()
**内部调用getPostMessage()
方法将runnable赋予msg.callback
,并在post()
中通过sendMessageDelayed()
方法调用sendMessageAtTime()方法
将msg压入MessageQueue
中