Handler机制之Looper介绍
1,Handler、MessageQueue、Looper三者之间的关系
- Handler和Looper的创建线程是相同的,而looper的内部还维护了一个MessageQueue的消息队列,该队列是链表实现的
- Handler通过sendMessage方法发送消息给Looper中对应的MessageQueue
- Looper通过消息循环获取消息后,会调用对应的消息中的target(target对应的是发消息的Handler)的dispatchMessage()方法来处理消息。
2,Looper的原理-如何与主线程关联的
消息队列(MessageQueue的创建是在Looper中内部创建的,同时Handler消息的发送与处理都是围绕着Looper来进行的
在Android中,App进程是由Zygote fork而创建的,而我们的ActivityThread就是运行在该进程下的主线程中,那么在ActivityThread的main方法中,Looper会通过prepareMainLooper()来创建内部的消息队列(MessageQueue),同时会通过loop()构建消息循环
Looper.prepareMainLooper();
// Find the value for {@link #PROC_START_SEQ_IDENT} if provided on the command line.
// It will be in the format "seq=114"
long startSeq = 0;
if (args != null) {
for (int i = args.length - 1; i >= 0; --i) {
if (args[i] != null && args[i].startsWith(PROC_START_SEQ_IDENT)) {
startSeq = Long.parseLong(
args[i].substring(PROC_START_SEQ_IDENT.length()));
}
}
}
ActivityThread thread = new ActivityThread();
thread.attach(false, startSeq);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
// End of event ActivityThreadMain.
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
继续查看Looper.prepareMainLooper()方法
//创建主线程的looper
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与当前主线程绑定
//quitAllowed:主线程的必须是false,主线程不允许手动退出
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对象
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
3,Looper的原理-内部创建消息队列
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
如上可以看出,消息队列是在创建looper对象的时候创建的
3,Looper的原理-消息循环
当前Looper对象与主线程关联后,最后一步会调用Looper对象中的loop()方法来开启消息循环
public static 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(); //该方法可能堵塞,
if (msg == null) {
//如果没有消息,表示当前消息队列已经退出
return;
}
...省略部分代码
try {
//获取消息后,执行发送消息的handler的dispatchMessage方法。
msg.target.dispatchMessage(msg);
end = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis();
} finally {
if (traceTag != 0) {
Trace.traceEnd(traceTag);
}
}
...省略部分代码
}
msg.recycleUnchecked();
}
}
如上所示,流程比较简单,就是looper一直从消息队列中获取消息,然后调用msg.target.dispatchMessage方法分发消息,如果没有消息,则退出循环