概述
- Looper在Android的消息机制中扮演着消息循环的角色,它会不停地从MessageQueue中查看是否有新消息,如果有新消息就会立刻处理,否则就一直阻塞在那里。
源码分析
构造方法
1 | private Looper(boolean quitAllowed) { |
但是这个构造方法是私有的,那么我们要怎么创建一个Looper呢?
创建Looper
prepare()
通过Looper.prepare()即可为当前线程创建一个Looper1
2
3
4
5
6
7
8
9
10public static void prepare() {
prepare(true);
}
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)); //这里调用构造方法
}
其中sThreadLocal是一个Looper类型的ThreadLocal变量1
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
prepareMainLooper()
Looper处理prepare方法,还提供了prepareMainLooper方法,这个方法主要是给主线程也就是ActivityThread创建Looper用的,我们一般不要去调用该方法。1
2
3
4
5
6
7
8
9public static void prepareMainLooper() {
prepare(false); //创建主线程的Looper
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
sMainLooper = myLooper(); //myLooper()返回当前线程的Looper对象
}
}
Looper还提供了getMainLooper方法获取到主线程的Looper1
2
3
4
5public static Looper getMainLooper() {
synchronized (Looper.class) {
return sMainLooper;
}
}
退出Looper
Looper提供了quit()和quitSafely()方法来退出一个Looper1
2
3public void quit() {
mQueue.quit(false);
}
1 | public void quitSafely() { |
两者的区别是:
- quit()会直接退出Looper
- quitSafely()只是设定一个退出标记,然后把消息队列中的已有信息处理完毕后才安全地退出
Looper退出后,通过Handler发送的消息会失败,其send方法返回false。
在子线程中,如果手动创建了Looper,那么在所有的事情完成以后应该调用quit方法来终止消息循环,否则这个子线程就会一直处于等待的状态。
而退出Looper之后,这个线程就会立刻终止,因此建议不需要的时候终止Looper。
Loop()
1 | /** |
- 当消息队列被标记位退出状态时,它的next方法就会返回null。也就是说,Looper必须退出,否则loop方法就会无限循环下去。
- 因为MessageQueue的next方法是一个阻塞操作,当没有消息时,next方法会一直阻塞在那里,这也导致loop方法一致阻塞在那里。
- msg.target.dispatchMessage(msg);通过这条语句,Handler发送的消息最终又交给了它的dispatchMessage方法来处理了。但由于是在创建Handler时所使用的Looper中执行的,这样就成功地将代码逻辑切换到了指定的线程中(创建Handler所在线程)执行。