本文为个人学习笔记分享,没有任何商业化行为,对其他文章的引用都会标记。如有侵权行为,请及时提醒更正!如需转载请表明出处
本文主要来源是 任玉刚大神的《Android开发艺术探索》
Looper在Android的消息机制中扮演者消息循环的角色,具体来说就是它会不停地从MessageQueue中查看是否有新消息,如果有就会立即处理,否则就一直阻塞在那里。首先看一下它地构造方法,在构造方法中它会创建一个MessageQueue即消息队列,然后将当前线程的对象保存起来,如下所示。
private Looper(boolean quitAllowed){
mQueue=new MessageQueue(quitAllowed);
mThread=Thread.currentThread();
}
我们知道,Handler的工作需要Looper,没有Looper的线程就会报错,那么如何为一个线程创建Looper呢?其实很简单,通过Looper.prepare()即可为当前线程创建一个Looper,接着通过Looper.looper()来开启消息循环,如下所示。
new Thread("Thread#2"){
@Override
public void run(){
Looper.prepare();
Handler handler=new Handler();
Looper.looper();
}
}
Looper除了prepare方法外,还提供了prepareMainLooper方法,这个方法主要是给主线程也就是ActivityThread创建Looper使用的,其本质也是通过prepare方法来实现。由于主线程的Looper比较特殊,所以Looper提供了一个getMainLooper的方法,通过它可以在任何地方获取到主线程的Looper。Looper也是可以退出的,Looper提供了quit和quitSafely来退出一个Looper,二者的区别是:quit会直接退出Looper,而quitSafely只是设定一个退出标记,然后把消息队列中的已有消息处理完毕才安全退出。Looper退出后,通过Handler发送的消息会失败,这个时候Handler的send方法返回false。在子线程中,如果手动为其创建了Looper,那么在所有的事情完成以后应该调用quit方法来终止循环消息,否则这个子线程就会一直处于等待的状态,而如果退出Looper以后,这个线程就会立刻终止,因此建议不需要的时候终止Looper。
总结
- Handler的工作需要Looper,没有Looper的线程就会报错,通过Looper.prepare()即可为当前线程创建一个Looper,接着通过Looper.looper()来开启消息循环
- Looper提供了一个getMainLooper的方法,通过它可以在任何地方获取到主线程的Looper。
- Looper提供了quit和quitSafely来退出一个Looper,二者的区别是:quit会直接退出Looper,而quitSafely只是设定一个退出标记,然后把消息队列中的已有消息处理完毕才安全退出。
- Looper退出后,通过Handler发送的消息会失败,这个时候Handler的send方法返回false。在子线程中,如果手动为其创建了Looper,那么在所有的事情完成以后应该调用quit方法来终止循环消息,否则这个子线程就会一直处于等待的状态,而如果退出Looper以后,这个线程就会立刻终止,因此建议不需要的时候终止Looper。
Looper中的loop
Looper中最重要的方法loop,只有调用loop后,消息循环系统才会真正起作用。
public static void loop() {
.......
for (;;) {
//开启无线循环 调用MessageQueue,当MessageQueue无数据时,阻塞。
Message msg = queue.next(); // might block
if (msg == null) {
// Looper退出的唯一情况就是MessageQueue的next方法返回null
return;
}
final long dispatchStart = needStartTime ? SystemClock.uptimeMillis() : 0;
final long dispatchEnd;
try {
//分发事件
msg.target.dispatchMessage(msg);
dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0;
} finally {
if (traceTag != 0) {
Trace.traceEnd(traceTag);
}
}
......
msg.recycleUnchecked();
}
}
Looper的loop方法的工作过程也比较好理解,loop方法是一个死循环,唯一跳出循环的条件就是MessageQueue的next方法返回null。当Looper的quit方法被调用时,Looper就会调用MessageQueue的quit或者quitSafely方法来通知消息队列退出,当消息队列被标记为退出状态时,它的next方法就会返回null。如果MessageQueue的next方法返回了新消息,Looper就会处理这条消息:msg.target.dispatchMessage(msg);这里msg.target就是发送了这个消息的handler对象,这样Handler发送的消息最终又会交给它的dispatchMessage方法。但是这里就不同了,Handler的dispatchMessage方法是在创建Handler时所使用的Looper中执行的,这样就成功的将代码逻辑切换到指定线程中去执行了。
总结
- Looper的loop方法的工作过程也比较好理解,loop方法是一个死循环,唯一跳出循环的条件就是MessageQueue的next方法返回null。
- 当Looper的quit方法被调用时,Looper就会调用MessageQueue的quit或者quitSafely方法来通知消息队列退出,当消息队列被标记为退出状态时,它的next方法就会返回null。
- MessageQueue的next方法返回了新消息msg.target.dispatchMessage(msg);这里msg.target就是发送了这个消息的handler对象,这样Handler发送的消息最终又会交给它的dispatchMessage方法。
整理写作不易,请小伙伴多多支持,麻烦请点赞关注支持一下,😘😘😘。
网友评论