Handler 机制分析
handler 使用方法大致如下:
HandlerThread handlerThread = new HandlerThread("HandlerThread");
handlerThread.start();
Handler mHandler = new Handler(handlerThread.getLooper()){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
Log.d("HandlerThreadActivity.class","uiThread2------"+Thread.currentThread());//子线程
}
};
Log.d("HandlerThreadActivity.class","uiThread1------"+Thread.currentThread());//主线程
Message msg = new Message();
mHandler.sendMessage(msg);
总的来说,就是 Looper 不断地从 MessageQueue 里拿出 Message 执行。而 Message 是通过 Handler 插入 MessageQueue 的.
从源码的角度分析一下整个流程:
1. HandlerThread 是 android 系统提供的线程类,此线程的 run 方法会执行以下两个方法:
Looper.prepare()和
Looper.loop(); 下面会分析这两个方法
2. Looper.prepare()。
此方法代码如下:
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
该方法是在当前线程创建一个 looper 对象并存储此对象在当前线程中。
3. 创建 handler 对象,会执行如下代码:
mQueue = mLooper.mQueue;
由上面代码可以看出,创建 handler 对象的时候会把 looper 对象中的 mQueue 赋值给 handler 对象中的 mQueue。
4. handler.sendMessage(Message msg)。
此方法实际是调用 enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis)
方法。
msg.target = this; // 把当前 handler 对象保存到 msg.target
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
queue.enqueueMessage(msg, uptimeMillis) 会把 message 对象给放到 mQueue 中
(mQueue 内部是使用单链表的形式存储 message 队列的。)
5. Looper.loop()
此方法代码如下:
final Looper me = myLooper();
final MessageQueue queue = me.mQueue;
...
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);
end = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis();
} finally {
if (traceTag != 0) {
Trace.traceEnd(traceTag);
}
}
...
msg.recycleUnchecked();
}
looper() 方法中有个死循环 for 方法,一直在取消息队列中 queue 中的消息, 然后对每个 msg
调用 msg.target.dispatchMessage(msg)。如刚才所写,msg.target 实际就是 handler 对象,
即调用 handler.dispatchMessage 方法,dispatchMessage 方法会调用 handleMessage(Message msg)
方法,这时就可以对消息进行处理了。消息处理机制大致如此。
线程中创建 handler 时需要保证该线程中存在 looper 对象
有人说在线程中创建 Handler 的实例时需要传入 Looper 实例。我想了想自己之前在 UI 线程使用
Handler 时 Handler 的构造函数传参是空的,也能正常使用 Handler。猜测 android 系统默认就在 UI 线程创建好了 Looper 实例。于是就去源码当中寻找答案。
android 启动 app 的入口 ActivityThread 的 main 方法调用了 Looper.prepareMainLooper()
方法。下面是 Looper.prepareMainLooper() 的实现:
public static void prepareMainLooper() {
prepare(false);
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
sMainLooper = myLooper();
}
}
此方法是在主线程创建了 Looper 的实例 sMainLooper,所以说主线中Handler 的构造函数传参为空也是能正常使用。