一、数据成员
每个Looper拥有一个消息队列,归属于一个线程。
1
2
3
4
5
6
7
8
9
10
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
// 由Looper.class控制,静态全局的MainLooper
private static Looper sMainLooper;
// Looper持有的MessageQueue
final MessageQueue mQueue;
// Looper所在的线程实例
final Thread mThread;
二、初始化
每个线程仅能创建一个Looper,如果线程尝试创建第二个Looper会引起异常。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public static void prepare() {
prepare(true);
}
private static void prepare(boolean quitAllowed) {
// ThreadLacal.get()的Looper不为空,表明之前已经初始化过了
if (sThreadLocal.get() != null) {
throw new RuntimeException(
"Only one Looper may be created per thread");
}
// 之前没有初始化则开始初始化
sThreadLocal.set(new Looper(quitAllowed));
}
先创建MessageQueue,并把线程实例保存到Looper中。方法是私有的,只能由prepare()
调用。
1
2
3
4
5
private Looper(boolean quitAllowed) {
// 创建Looper时为这个Looper创建对应的MessageQueue
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
Runtime通过这个方法自动创建主线程Looper,千万不要在主线程中再次调用这个方法。而 sMainLooper 是静态变量,所以任意 Looper 都能通过 sMainLooper 向主线程发送消息。
1
2
3
4
5
6
7
8
9
10
11
12
13
public static void prepareMainLooper() {
// 主线程的消息队列禁止退出
prepare(false);
// 且每个进程只有一个MainLooper
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException(
"The main Looper has already been prepared.");
}
sMainLooper = myLooper();
}
}
三、启动Looper
启动 Looper 的 MessageQueue。关于在 queue.next() 上阻塞请看 MessageQueue源码 - 5.5 next
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
public static void loop() {
final Looper me = myLooper();
// Looper没有通过prepare()方法初始化就抛出异常
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
// 从Looper中获取其MessageQueue
final MessageQueue queue = me.mQueue;
// 作用是清空远程调用端的uid和pid,用当前本地进程的uid和pid替代
Binder.clearCallingIdentity();
final long ident = Binder.clearCallingIdentity();
// 循环遍历,从消息队列取消息
for (;;) {
// 如果队列没有消息,queue.next()内部会阻塞等待
Message msg = queue.next();
// 队列返回null表明消息队列已经关闭
if (msg == null) {
// 消息队列关闭,Looper退出
return;
}
// 通过对应的Handler进行回调
msg.target.dispatchMessage(msg);
// 确保消息在分发的时候线程没有出错
final long newIdent = Binder.clearCallingIdentity();
if (ident != newIdent) {
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);
}
// 消息体回收
msg.recycleUnchecked();
}
}
四、消息队列退出
消息队列关闭
1
2
3
public void quit() {
mQueue.quit(false);
}
消息队列安全关闭
1
2
3
public void quitSafely() {
mQueue.quit(true);
}
五、一般方法
返回Looper所属线程和消息队列
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public @NonNull Thread getThread() {
return mThread;
}
public @NonNull MessageQueue getQueue() {
return mQueue;
}
// 所有Looper实例持有同一个静态sMainLooper
public static Looper getMainLooper() {
synchronized (Looper.class) {
return sMainLooper;
}
}
返回所属线程的Looper。如果子线程没有调用Looper.prepare(),sThreadLocal.get()为空。
1
2
3
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
获取线程Looper的消息队列
1
2
3
public static @NonNull MessageQueue myQueue() {
return myLooper().mQueue;
}
返回当前的线程是否就是Looper的线程
1
2
3
public boolean isCurrentThread() {
return Thread.currentThread() == mThread;
}