源码分析Looper、Handler、Message之间的关系

/**   

            Handler、Looper、Message三者之间的关系,无外乎就是开始Looper会开始无限的循环,目的是在消息队列中进行获取Message,有则取无在等;而Handler则是在发送Message和handlerMessage方面起作用,发送的Message则是发送到消息队列中,handlerMessage则是处理Looper发过来的消息

*/

先附一张三者关系图方便理解


源码分析

首先我们来看一下Handler的构造方法

    /**
     * Default constructor associates this handler with the queue for the
     * current thread.
     *
     * If there isn't one, this handler won't be able to receive messages.
     */
    public Handler() {
        ...
        //获取Looper对象 
       mLooper = Looper.myLooper();
       if (mLooper == null) {
            throw new RuntimeException(
                "Can't create handler inside thread that has not called Looper.prepare()");
        }
        mQueue = mLooper.mQueue;
        mCallback = null;
    }
      这里有一个判断,这里的判断主要的针对子线程new Handler的情况,因为在主线程Looper会自动创建在子线程里则没有。

为了验证我们来看主线程的方法ActivityThread类main方法

    public static final void main(String[] args) {
        ...
        Looper.prepareMainLooper();
        if (sMainThreadHandler == null) {
            sMainThreadHandler = new Handler();
        }

        ActivityThread thread = new ActivityThread();
        thread.attach(false);

        if (false) {
            Looper.myLooper().setMessageLogging(new
                    LogPrinter(Log.DEBUG, "ActivityThread"));
        }

        Looper.loop();
        ...
    }
}
Looper.prepareMainLooper()

    public static final void prepare() {
        if (sThreadLocal.get() != null) {
            throw new RuntimeException("Only one Looper may be created per thread");
        }
        sThreadLocal.set(new Looper());
    }
    
    public static final void prepareMainLooper() {
        prepare();
        setMainLooper(myLooper());
        if (Process.supportsProcesses()) {
            myLooper().mQueue.mQuitAllowed = false;
        }
    }
         从代码中可以看出其实main方法就是调用了prepare方法,而这个方法是将new Looper()放入ThreadLocal里面,所谓ThreadLocal类也HashMap是一样的,只不过它里面默认是将Key存储的每个线程,用途:保证每个线程所拥有的value是唯一的。ok,我们接下来看Handler的构造方法

Looper.myLooper()方法

    /**
     * Return the Looper object associated with the current thread.  Returns
     * null if the calling thread is not associated with a Looper.
     */
    public static final Looper myLooper() {
        return (Looper)sThreadLocal.get();
    }
这里只是将ThreadLocal类里面存入的Looper取出来,然后我们看ActivityThread类里面

Loop.loop()方法

   /**
     *  Run the message queue in this thread. Be sure to call
     * {@link #quit()} to end the loop.
     */
    public static final void loop() {
        Looper me = myLooper();
        MessageQueue queue = me.mQueue;
        ...
        while (true) {
            Message msg = queue.next(); // might block
            //if (!me.mRun) {
            //    break;
            //}
            if (msg != null) {
                if (msg.target == null) {
                    // No target is a magic identifier for the quit message.
                    return;
                }
                msg.target.dispatchMessage(msg);
                ...
            }
        }
    }
      调用这个方法就进入了无限循环中,Looper将从MessageQueue中不断的取消息(有的时候则取没有的时候等待),当取到数据的时候会调用msg.target.dispatchMessage(msg)方法将Message回传到Handler中。target是什么呢?其实你顺着源码查看你会发现target其实是Handler对象,更准确的是该Message所属Handler对象。

msg.target.dispatchMessage(msg)方法

    /**
     * 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和mCallback在Message和Handler创建的时候有相应的参数,这里最后的情况才是去执行handler的handlerMessage方法,这里需要注意喽, 如果你在Message和Handler里面使用Callback就不会在调用handlerMessage。

对于Looper取消息和发送消息就是这些,接下来来看一下Handler的发送消息到消息队列的过程

最终调用的sendMessageAtTime()方法

    public boolean sendMessageAtTime(Message msg, long uptimeMillis)
    {
        boolean sent = false;
        MessageQueue queue = mQueue;
        if (queue != null) {
            msg.target = this;
            sent = queue.enqueueMessage(msg, uptimeMillis);
        }
        else {
            RuntimeException e = new RuntimeException(
                this + " sendMessageAtTime() called with no mQueue");
            Log.w("Looper", e.getMessage(), e);
        }
        return sent;
    }
      每次的发送中将当前发送的Handler对象赋值给target ,整好对应上面Looper取出Message之后根据target分发给相应的Handler的过程。

MessageQueue.enqueueMessage()方法

    final boolean enqueueMessage(Message msg, long when) {
        ...
            msg.when = when;
            //Log.d("MessageQueue", "Enqueing: " + msg);
            Message p = mMessages;
            if (p == null || when == 0 || when < p.when) {
                msg.next = p;
                mMessages = msg;
                needWake = mBlocked; // new head, might need to wake up
            } else {
                Message prev = null;
                while (p != null && p.when <= when) {
                    prev = p;
                    p = p.next;
                }
                msg.next = prev.next;
                prev.next = msg;
                needWake = false; // still waiting on head, no need to wake up
            }
        }
        if (needWake) {
            nativeWake(mPtr);
        }
        return true;
    }

在第一个if语句中通过比较传入的when和队列中第一个Message的when的大小,如果传入的小则需要马上进行处理,将needWake唤醒的状态置为true

否则的话将对消息队列进行遍历将传入的Message根据when插入到里面,并且将唤醒状态置为false。


到这里三者关系就大致讲完了,如果想了解更多请看鸿洋大神的: Android 异步消息处理机制 让你深入理解 Looper、Handler、Message三者关系

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值