android消息机制1-整体概览

来源:互联网 发布:linux多线程并发编程 编辑:程序博客网 时间:2024/06/16 13:34

应用程序入口:

ActivityThread类中

public static void main(String[] args) {        Looper.prepareMainLooper();    ActivityThread thread = new ActivityThread();    thread.attach(false);    // End of event ActivityThreadMain.     Looper.loop();    throw new RuntimeException("Main thread loop unexpectedly exited");}

可以知道,程序初始化就会在主线程预加载MainLooper

public static void prepareMainLooper() {    prepare(false);    ...        sMainLooper = myLooper();    }}


private static void prepare(boolean quitAllowed) {    sThreadLocal.set(new Looper(quitAllowed));}

public static @Nullable Looper myLooper() {    return sThreadLocal.get();}


以上就是Looper.prepareMainLooper()的过程,可以看出先在ThreLocal准备Looper对象,然后get Looper对象,先设置后获取再使用,不会为null

额外提一下ThreadLocal是个什么类?

* Implements a thread-local storage, that is, a variable for which each thread* has its own value. All threads share the same {@code ThreadLocal} object,* but each sees a different value when accessing it, and changes made by one* thread do not affect the other threads.
就是说作用范围线程域,同一进程中的所有线程共享这个对象,但是每个线程根据其映射的值又不同

举个栗子,月亮只有一个,每个人中秋晚上赏月看到的月亮都不同

然后Looper进行loop()

public static void loop() {    final Looper me = myLooper();       final MessageQueue queue = me.mQueue;    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;        }        msg.target.dispatchMessage(msg);        msg.recycleUnchecked();    }}

看loop的过程,先得到消息队列queue=me.mQueue,这个队列是什么时候初始化的呢

private Looper(boolean quitAllowed) {    mQueue = new MessageQueue(quitAllowed);    mThread = Thread.currentThread();}
是在给ThreadLocal绑定Looper时候初始化的。

既然消息队列有了,那就一个一个开始取吧,永真循环就开始了

当取到了消息之后,Handler就会分发消息dispatchMessage(msg)

岔开说一下,msg.target就是发送该消息的Handler对象

每一个轮询出来的消息都会持有一个发送该消息的引用,因为入队列时就保证了target不为null

源码在Handler中如下

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

回归主线,Hander分发消息

public void dispatchMessage(Message msg) {    if (msg.callback != null) {        handleCallback(msg);    } else {        if (mCallback != null) {            if (mCallback.handleMessage(msg)) {                return;            }        }        handleMessage(msg);    }}

如果没有msg的Runnable任务或者Handler的回调,那么就会调用handleMessage(msg),这个方法就是调用者实现。

至此消息机制的整体流程讲完了。

有几个问题还要讲下:

1,既然是Looper一直在死循环,为何不引起阻塞,对性能有何影响

答案是linux的管道通信机制