美文网首页Android进阶之路Android技术知识Android开发
10分钟掌握Android消息机制(三)Looper的工作原理

10分钟掌握Android消息机制(三)Looper的工作原理

作者: 夏天吃冰棍 | 来源:发表于2019-06-18 00:45 被阅读4次

本文为个人学习笔记分享,没有任何商业化行为,对其他文章的引用都会标记。如有侵权行为,请及时提醒更正!如需转载请表明出处
本文主要来源是 任玉刚大神的《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方法。
    整理写作不易,请小伙伴多多支持,麻烦请点赞关注支持一下,😘😘😘。

相关文章

网友评论

    本文标题:10分钟掌握Android消息机制(三)Looper的工作原理

    本文链接:https://www.haomeiwen.com/subject/wvbtqctx.html