源码分析Android消息传递机制

来源:互联网 发布:怪物猎人捏脸数据女 编辑:程序博客网 时间:2024/05/24 06:05

基础知识:理解和使用Handler需要用到四个类:Handler,Looper,Message,MessageQueue。这四个类是如何交互的呢?

大概思路:(1)发送消息: handler发送message消息,looper将消息放到messageQueue;(2)处理消息:Looper在创建后会开启一个死循环,这个死循坏会读取messageQueue里面的message,一旦有消息,机会马上回调handler的那个handleMessage方法。

一,主线程中的消息传递过程分析

要使用消息传递,每个线程内部都有必须一个Looper和MessageQueue,也就是说在线程启动是就需要创建Looper对象和MessageQueue对象,主线程的Looper在哪里创建额呢?看如下源代码:在ActivityThread类

public static void main(String[] args) {
Looper.prepareMainLooper();ActivityThread thread = new ActivityThread();thread.attach(false);if (sMainThreadHandler == null) {    sMainThreadHandler = thread.getHandler();}if (false) {    Looper.myLooper().setMessageLogging(new            LogPrinter(Log.DEBUG, "ActivityThread"));}// End of event ActivityThreadMain.Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);Looper.loop();

}
主要留意里面的Looper.prepareMainLooper()和Looper.loop();
进入Looper类的prepareMainLooper方法
public static void prepareMainLooper() {    prepare(false);    synchronized (Looper.class) {        if (sMainLooper != null) {            throw new IllegalStateException("The main Looper has already been prepared.");        }        sMainLooper = myLooper();    }}
private static void prepare(boolean quitAllowed) {    if (sThreadLocal.get() != null) {        throw new RuntimeException("Only one Looper may be created per thread");    }    sThreadLocal.set(new Looper(quitAllowed));}
可以看到在prepare方法里面
sThreadLocal.set(new Looper(quitAllowed));将Looper对象创建后存储成ThreadLocal类型的对象(ThreadLocal可以自行百度,比较简单)。
这个时候Looper创建完成了,那么MessageQueue对象又是在哪里创建的呢?
private Looper(boolean quitAllowed) {    mQueue = new MessageQueue(quitAllowed);    mThread = Thread.currentThread();}
就在刚刚创建Looper的同是也创建了MessageQueue对象,messageQueue对象是Looper的内部成员。
因此执行Looper.prepareMainLooper()后Looper和MessageQueue就创建完成了。然后又调用了Looper.loop()
进入Looper类的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;    // Make sure the identity of this thread is that of the local process,    // and keep track of what that identity token actually is.    Binder.clearCallingIdentity();    final long ident = Binder.clearCallingIdentity();    for (;;) {        Message msg = queue.next(); // might block        if (msg == null) {            // No message indicates that the message queue is quitting.            return;        }        // This must be in a local variable, in case a UI event sets the logger        Printer logging = me.mLogging;        if (logging != null) {            logging.println(">>>>> Dispatching to " + msg.target + " " +                    msg.callback + ": " + msg.what);        }        msg.target.dispatchMessage(msg);        if (logging != null) {            logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);        }        // Make sure that during the course of dispatching the        // identity of the thread wasn't corrupted.        final long newIdent = Binder.clearCallingIdentity();        if (ident != newIdent) {            Log.wtf(TAG, "Thread identity changed from 0x"                    + Long.toHexString(ident) + " to 0x"                    + Long.toHexString(newIdent) + " while dispatching to "                    + msg.target.getClass().getName() + " "                    + msg.callback + " what=" + msg.what);        }        msg.recycleUnchecked();    }}
很明显是一个死循环,不断的读取MessageQueue里面的消息,跳出这个循环的条件是
queue.next()为null。所以Looper.loop()的作用是开启一个消息循环传递系统,一旦有消息发送过来(MessageQueue有消息),就会处理。
上面是主线程Looper的创建过程(子线程创建过程基本一样),接下来是发送消息,然后处理消息。发送消息和处理消息的实现逻辑主要在Handler类里面。所以首先是创建一个handler对象,留意如下源码:
handler有很多重载构造方法但是最后都会走如下的构造方法
public Handler(Callback callback, boolean async) {    if (FIND_POTENTIAL_LEAKS) {        final Class<? extends Handler> klass = getClass();        if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&                (klass.getModifiers() & Modifier.STATIC) == 0) {            Log.w(TAG, "The following Handler class should be static or leaks might occur: " +                klass.getCanonicalName());        }    }    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;}
可以看到handler内部一定需要的两样东西即使Looper和MessageQueue,而Looper和MessageQueue都可以直接通过Looper类获取。
handler对象创建后就可以发送message了,同样发送消息也会有很多接口方法,但是最后都会调用如下方法:
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);}
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {    msg.target = this;    if (mAsynchronous) {        msg.setAsynchronous(true);    }    return queue.enqueueMessage(msg, uptimeMillis);}
这样就把消息入去到MessageQueue中,注意一下msg.target = this; target是Message内部的成员变量类型是Handler,这个的作用是在Looper启动的消息循环中,当消息对象获取到Message时,就可以通过message内部的handler来做回调处理回到刚刚Looper.loop()方法里面,里面有msg.target.dispatchMessage(msg);这行代码,再看看在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这个方法,至于通过callBack来处理还是直接的handleMessage都是可以选择的。
到这里handler的消息处理源码实现大概是这样。
二,子线程中消息传递。
如果自己新建一个子线程,然后在子线程内部进行消息传递,实现过程跟在ActivityThread中的差不多,不一样地方主要是是在子线程中创建Looper和messageq调用的方法是Looper.prepare(),但是一样会进过prepare这个方法来创建。

1 0
原创粉丝点击