系列目录: Handler机制原理
1.prepareMainLooper()
//Looper#prepareMainLooper
public static void prepareMainLooper() {
// 设置不允许退出的Looper
prepare(false);
synchronized (Looper.class) {
//将当前的Looper保存为Looper。每个线程只允许执行一次
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
sMainLooper = myLooper();
}
}
2.prepare()
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
//Looper#prepare
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));
}
boolean quitAllowed
表示Looper是否允许退出,true就表示允许退出,对于false则表示Looper不允许退出
sThreadLocal
的作用已在之前文章中做过解析,异步ThreadLocal
3. Looper()
//Looper#Looper
private Looper(boolean quitAllowed) {
// 创建MessageQueue对象
mQueue = new MessageQueue(quitAllowed);
// 记录当前线程
mThread = Thread.currentThread();
}
4. myLooper()
//Looper#myLooper
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
sThreadLocal.get()是和prepare(boolean)方法里面的sThreadLocal.set(new Looper(quitAllowed))一一对应的。
5. loop()
//Looper#loop
public static void loop() {
// 获取TLS存储的Looper对象
final Looper me = myLooper();
//没有Looper 对象,直接抛异常
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
//获取当前Looper对应的消息队列
final MessageQueue queue = me.mQueue;
// Make sure the identity of this thread is that of the local process,
// and keep track of what that identity token actually is.
Binder.clearCallingIdentity();
// 确保权限检查基于本地进程,而不是基于最初调用进程
final long ident = Binder.clearCallingIdentity();
// 进入 loop的主循环方法
// 一个死循环,不停的处理消息队列中的消息,消息的获取是通过MessageQueue的next()方法实现
for (;;) {
// 可能会阻塞
Message msg = queue.next(); // might block
// 如果没有消息,则退出循环
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
// This must be in a local variable, in case a UI event sets the logger
// 默认为null,可通过setMessageLogging()方法来指定输出,用于debug功能
Printer logging = me.mLogging;
if (logging != null) {
logging.println(">>>>> Dispatching to " + msg.target + " " +
msg.callback + ": " + msg.what);
}
// 用于分发消息,调用Message的target变量(也就是Handler了)的dispatchMessage方法来处理消息
msg.target.dispatchMessage(msg);
if (logging != null) {
logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
}
// Make sure that during the course of dispatching the
// identity of the thread wasn't corrupted.
// 确保分发过程中identity不会损坏
final long newIdent = Binder.clearCallingIdentity();
if (ident != newIdent) {
// 打印identiy改变的log,在分发消息过程中是不希望身份被改变
Log.wtf(TAG, "Thread identity changed from 0x"
+ Long.toHexString(ident) + " to 0x"
+ Long.toHexString(newIdent) + " while dispatching to "
+ msg.target.getClass().getName() + " "
+ msg.callback + " what=" + msg.what);
}
// 将Message放入消息池
msg.recycleUnchecked();
}
}
loop进入循环模式,不断重复下面的操作
- 读取MessageQueue的下一条Message
- 把Message分发给相应的target
- 再把分发后的Message回到消息池,以便重复利用
6. quit()
//Looper#quit
public void quit() {
mQueue.quit(false);
}
退出循环
将终止(loop()方法)而不处理消息队列中的任何更多消息
7. quitSafely()
//Looper#quitSafely
public void quitSafely() {
mQueue.quit(true);
}
处理完MessageQueue内当前的Messager列表后退出循环
网友评论