【Android消息机制】简要分析(一)

来源:互联网 发布:淘宝怎么更换图片 编辑:程序博客网 时间:2024/06/05 02:51

主要组成概述:Hanlder、MessageQueue以及Looper

1.Handler:线程切换

2.MessageQueue:用来存储信息 内部实现是单链表而不是队列。

3.Looper:无限循环的方式去查找是否有消息

备注:Looper中一个ThreadLocal的概念
作用:是来存储每一个线程中数据。
用途:Hanlder创建的时候会采用当前线程的Looper来构造消息循环系统,Handler正式通过ThreadLocal来获取当前的线程Looper的。

源代码

1.Handler是如何将三者联系起来的?

看看Handler创建源代码:

public Handler(Callback callback, boolean async) {        ...//省略        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 = callback;        mAsynchronous = async;    }

到调用了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 Looper myLooper() {        return sThreadLocal.get();    }

没错,的确是这样印证了Handler、Looper的关系。

那么MessageQueue是如何一起协同工作呢?

我们看到mQueue = mLooper.mQueue;

所以从不难推断出MessageQueue在Looper初始化的时候也一并初始化了。

从这里我们也可以看出:无论我们在主线程创建多少个Handler,他们公用一个消息队列的

2.Looper是如何工作的?

上面概述的时候我们知道,Looper是负责从消息队列中读取消息,然后回传到handler的handleMessage方法来处理消息的。

大家不知道还记不记得,我们是如何在子线程创建一个Handler的? 我们需要调用Looper.prepare()来准备一个Looper,并且调用Looper.loop()。

很明显Looper.loop()就是无限读取消息队列的奥秘所在。

源代码(省略了部分):

/**     * Run the message queue in this thread. Be sure to call     * {@link #quit()} to end the loop.     */    public static void loop() {        final Looper me = myLooper();        if (me == null) {            throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");        }        final MessageQueue queue = me.mQueue;        ...        for (;;) {            Message msg = queue.next(); // might block            if (msg == null) {                // No message indicates that the message queue is quitting.                return;            }           ...            msg.target.dispatchMessage(msg);            ...        }    }    /**     * Return the Looper object associated with the current thread.  Returns     * null if the calling thread is not associated with a Looper.     */    public static Looper myLooper() {        return sThreadLocal.get();    }

第一步:先调用了Looper.myLooper()这个方法,返回当前线程所在的Looper实例。备注:这里也刚好可以看到了ThreadLocal的用途了。

第二步:无限死循环 如果有消息来了就:msg.target.dispatchMessage(msg);

这个msg.target是什么呢? 通过Message源代码发现 就是发送这个msg对象的Handler实例: Handler target;

那msg是什么时候保存的呢?通过Handler源代码发现:

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

msg在入队前,保存了这个handler实例的引用。

然后调用了这个Hanlder实例的dispatchMessage的方法。

那我们来看看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);        }    }

我们看到一句很重点的:handleMessage(msg);
实际上他是一个空方法:

    public void handleMessage(Message msg) {    }

这个就是为什么我们创建Handler之后要重写这个方法来处理消息了。

-Hans 2016.2.25 23:45

0 0
原创粉丝点击