zoukankan      html  css  js  c++  java
  • 06_消息机制的原理(2)

    ActivityThread是不需要程序员去调用的,ActivityThread是你看不到的。整个应用跑起来首先最先执行的就是ActivityThread.ActivityThread有一个main方法.应用一跑起来ActivityThread实际上就是主线程,主线程一上来首先就prepareMainLooper()和Looper.loop()。

    所以主线程里面写代码并没有写跟Looper和MessageQueue相关的东西。咱们直接搞了一个Handler,然后就直接开始发消息了。因为Looper和MessageQueue不需要咱们去写,主线程帮咱们都已经预备好了。接下来发消息实际上就是一个把消息放到消息队列进行管理的这么一个过程。

    在MessageQueue这个类里面只记住了消息队列的第一条消息。这里边每一个消息都有一个next。这个next它指向了下一条消息。sendMessage(),开了一个子线程。在主线程里面创建了一个Handler,Handler里面有一个成员变量:Looper。Handler一new出来的时候首先它就跟当前的这个主线程的Looper建立起了对应关系。Handler对应着主线程的Looper.那我在子线程里面想发一条消息,在这儿我可以去创建出一个消息:Message.通过Handler调它的sendMessage()方法,就把这个消息想办法放到消息队列里。放到这个消息队列里怎么去放?Message有一个属性叫when,这个when怎么去获取的,这就跟当前的开机多长时间还有Handler的另外一个方法叫sendMessageDelayed可以延迟一段时间.如果sendMessage()直接发的话那么延迟时间是0.这个when就是当前开机的时间。如果sendMessageDelayed就是当前开机的时间再加上延迟的时间。sendMessage实际上就是拿着这条消息跟消息队列的每一条消息挨着个去比这个when,谁这个when比较小那说明我这个消息要优先执行。优先执行的话那我就排的靠前。如果它是最前面的一条的话,那我的MessageQueue就会把这条消息给它记住。它这条消息的next又指向了下一条消息。所以整个发消息的过程就是把Message放到消息队列里的一个合适的位置。那这个Looper它要干什么事呢?就是去取消息。取消息之后它要丢给Handler去处理,取消息实际上Looper就不断地去查看这里面(MessageQueue消息队列)的消息。究竟什么时候执行?就取决于这个when。每一个消息都有一个when,Looper有一个Looper.loop()这个方法.Looper.loop()这个方法实际上它就是不断地调MessageQueue还有一个next(),如果调next()方法发现这一条消息到了该执行的时间了就把这条消息丢给了Handler去处理。那这个时候一旦出队了之后调它的handleMessage最终消息执行完了它会被回收掉,那这条消息就完了。那这个时候下一条消息就成了消息队列里的第一条消息。那这个时候Looper.loop()就要看下一条消息的when.如果它到点了就给它执行,如果没到点就等,等到它到时间。一到时间之后就把这条消息也取出来,取出来之后又丢给了Handler.那为什么咱们这个消息马上就得到了执行?因为咱们调的是sendMessage这个方法。sendMessage就是当前系统开机时间,when这个值就是当前的这个时间。当前的这个时间说明这条消息需要立即执行。需要立即执行那我这条消息刷过来之后,从子线程刷到消息队列MessageQueue之后发现立刻执行马上就丢给了Handler.Looper就把消息丢给了Handler.然后这条消息就执行掉了。还是要注意一点的是我这条消息实际上有一个消息池,所以咱们要获取消息的时候尽量不要去new,咱们有一个Message obtain这个方法。sPool实际上也是一个Message。所以想用到消息池的话一定要用obtain方法。否则你new的话就用不到它从中的机制了。那就会创建出一个新的消息对象。

        /**
         * Enqueue a message into the message queue after all pending messages
         * before (current time + delayMillis). You will receive it in
         * {@link #handleMessage}, in the thread attached to this handler.
         *  
         * @return Returns true if the message was successfully placed in to the 
         *         message queue.  Returns false on failure, usually because the
         *         looper processing the message queue is exiting.  Note that a
         *         result of true does not mean the message will be processed -- if
         *         the looper is quit before the delivery time of the message
         *         occurs then the message will be dropped.
         */
        public final boolean sendMessageDelayed(Message msg, long delayMillis)
        {
            if (delayMillis < 0) {
                delayMillis = 0;
            }
            return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
        }

        /**
         * Return a new Message instance from the global pool. Allows us to
         * avoid allocating new objects in many cases.
         */
        public static Message obtain() {
            synchronized (sPoolSync) {
                if (sPool != null) {
                    Message m = sPool;
                    sPool = m.next;
                    m.next = null;
                    sPoolSize--;
                    return m;
                }
            }
            return new Message();
        }
        private static Message sPool;

    整个的过程实际上就是通过Handler发一个消息, 发一个消息实际上丢给了MessageQueue对消息进行排序,一旦入队了这个Looper在恰当的时间会把消息队列里的时间取出来,取出来之后它就丢给了Handler的handleMessage处理消息。由于主线程Looper和MessageQueue都已经帮咱们准备好了,所以咱们只需要写Handler,用它发消息然后在handleMessage里面去处理消息。这个就是消息机制的原理。

  • 相关阅读:
    依赖注入(DI)和Ninject
    Dapper.NET——轻量ORM
    优化SQL查询:如何写出高性能SQL语句
    Razor语法
    sublime Text 3 官方版 3114 注册码
    数据库索引,存储过程,视图,事务
    Action向视图传值的6种方式
    C#知识点提要
    算法总结
    c++ 构造函数,拷贝构造函数,析构函数与赋值操作符
  • 原文地址:https://www.cnblogs.com/ZHONGZHENHUA/p/7064891.html
Copyright © 2011-2022 走看看