新手学习android源码(一) 学习Handler,Looper,MessageQueue

Handler , MessageQueue,Looper关系:

    Message 里有一个Handler属性

    Looper 里有一个MessageQueue属性

    Handler 里有一个MessageQueue(就是Looper里的), Looper

   创建的Handler的时候,会给Looper属性赋值,这个是从当前线程中拿出来的。ui线程里自带一个,其他线程里只能手动的

    Looper.prepare() 和 Looper.loop()

    Looper.prepare() 里看当前线程有没有绑定Looper,没有的话创建一个

    创建Looper时候,会给MessageQueue赋值。一个 Looper 对应一个MessageQueue

   

    一个Handler把 Message 加到MessageQueue中,Looper负责从MessageQueue里取Message,然后分发给Handler

    

 ----------------------------------------Handler发送消息到消息队列-----------------------------------------------

    Handler.sendMessage();内部还是调用的sendMessageDelayed() ,只不过延时时间设为0

    调用顺序是:sendMessage-->sendMessageDelayed()-->sendMessageAtTime()-->enqueueMessage()(仅仅给Message设一个target-->queue.enqueueMessage()

  public final boolean sendMessageDelayed(Message msg, long delayMillis)
    {
        if (delayMillis < 0) {
            delayMillis = 0;
        }
        return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
    }
 public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
        MessageQueue queue = mQueue;
        if (queue == null) {
            RuntimeException e = new RuntimeException(
                    this + " sendMessageAtTime() called with no mQueue");
            Log.w("Looper", e.getMessage(), e);
            return false;
        }
        return enqueueMessage(queue, msg, uptimeMillis);
    }

    可以看到最后一行, enqueueMessage()

 private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
        msg.target = this;
        if (mAsynchronous) {
            msg.setAsynchronous(true);
        }
        return queue.enqueueMessage(msg, uptimeMillis);
    }

   这个方法主要就是把Message的target设为this,将来循环从MessageQueue取Message,可以根据target,执行相应的handleMessage()。

    看最后一行,Handler的enqueueMessage又调用了queue.enqueueMessage();

    首先先看,enqueueMessage的方法签名:  boolean enqueueMessage(Message msg, long when) 。

    参数 when,就是Message被分发给handler的时间

    例如:当我们调用的是handler.sendMessageDelayed(1000); 此时的when=SystemClock.uptimeMillis() + 1000

新手学习android源码(一) 学习Handler,Looper,MessageQueue_第1张图片新手学习android源码(一) 学习Handler,Looper,MessageQueue_第2张图片    

    -------------------------------------Looper从MessageQueue取出Message------------------

    新手学习android源码(一) 学习Handler,Looper,MessageQueue_第3张图片新手学习android源码(一) 学习Handler,Looper,MessageQueue_第4张图片

再看handler.dispatchMessage()方法

 /**
     * Handle system messages here.
     */
    public void dispatchMessage(Message msg) {
        if (msg.callback != null) {
            handleCallback(msg);
        } else {
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            handleMessage(msg);
        }
    }

    先看msg.callback 是不是为空。这个callback到底是什么呢?

    handler.send(Runnable runnable).

    这个方法允许传一个Runnable的对象进去,在里面调用了下面的方法,把Runnable对象包装成了Message。

    private static Message getPostMessage(Runnable r) {
        Message m = Message.obtain();
        m.callback = r;
        return m;
    }

    这时Message.callback = r;

    这时再看dispatchMessage里如果callback不为空, 则调用    handleCallback(msg);执行

  private static void handleCallback(Message message) {
        message.callback.run();
    }

    

 -----------------------------------------Looper 退出------------------------------------------

    Looper.quit()

  public void quit() {
        mQueue.quit(false);
    }

    当调用了这个方法后,再调用handler.sendMessage(Message)添加Message到MessageQueue ,就会返回false;

    这个方法是不安全的,因为在Looper终止之前,可能还有一些Message没有被交付完。全部被取消了

    所以推荐使用Looprt.quitSafely(),注意这要api 18 以上才可以使用

public void quitSafely() {
        mQueue.quit(true);
    }

    可以看到这两个方法都是调用mQueue.quit(); 只是传进去的参数不一样

 void quit(boolean safe) {
        if (!mQuitAllowed) {
            throw new IllegalStateException("Main thread not allowed to quit.");
        }
        synchronized (this) {
            if (mQuitting) {
                return;
            }
            mQuitting = true;
            if (safe) {
                removeAllFutureMessagesLocked();
            } else {
                removeAllMessagesLocked();
            }
            // We can assume mPtr != 0 because mQuitting was previously false.
            nativeWake(mPtr);
        }
    }

其中,当正在退出时返回,否则将mQuitting标识为true

并且根据传进来的true或者false来决定时哪种退出的策略

removeAllFutureMessagesLocked();   ///这种是先看队首,如果执行时间没到,那说明后续的都没有到。则直接调用              removeAllMessagesLocked();否则,从队首一个一个往后找,直接找到第一个时间没到的Message m,从他开始一直到最后直接删除。那么m之前的是还能分发出去的。

removeAllMessagesLocked(); ///这种是直接删除MessageQueue上所有的Message

 

    


 

你可能感兴趣的:(新手学习android源码(一) 学习Handler,Looper,MessageQueue)