2.消息事件分发

2017-06-02  本文已影响0人  Varmin

什么是消息机制,概述:

Android的消息机制主要是指Handler的运行机制,以及Handler所附带的MessageQueue和Looper的工作过程。即:消息的发送,以及消息的分发过程。

为什么需要消息机制:

Android规定访问UI只能在主线程中进行,在子线程中访问UI就会抛异常。但是Android又不建议在主线程中做耗时操作,会可能导致ANR。所以,我们需要,能在子线程中做完耗时操作,然后去到主线程更新UI的办法。
Hander的主要作用是将一个任务切换到指定的线程中去执行。因此,系统提供Handler主要是为了解决在子线程中无法访问UI的问题。

发送消息:

handler中有众多的send方法,时间点的区别而已,到最后都会调用下面的方法,把message放入消息队列

//handler.post  view.post中的参数都是一个runnable对象,分装成一个Message
private static Message getPostMessage(Runnable r) {
        Message m = Message.obtain();
        m.callback = r;
        return m;
    }

//msg插入队列 
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
        //注意此处,this指的是handler自己
        msg.target = this;
        if (mAsynchronous) {
            msg.setAsynchronous(true);
        }
        //把消息插入队列
        return queue.enqueueMessage(msg, uptimeMillis);
    }
    

分发消息:

loop将队列中的msg一个一个取出,分发到各自的handler中处理。handler根据是否有callback选择不同的分发方式。

//Looper.loop(),省略了部分代码
public static void loop() {
        final Looper me = myLooper();
        final MessageQueue queue = me.mQueue;
        //死循环。唤醒/挂起?
        for (;;) {
            //next方法会阻塞线程,有消息就取出,没消息就等待。
            Message msg = queue.next();
            //加入消息队列时,target == handler,分发的时候就可以找到原来的handler,让其自己处理。
            //所以,一个线程多个handler发送消息,虽然都在一个队列里,但是还是会分发到原来的handler处理消息。
            msg.target.dispatchMessage(msg);
        }
    }
    
//由target返回到Handler中执行分发。
//加入队列的:有的是Runnable封装的message,有的是callback,有的是message,在这里分发   
public void dispatchMessage(Message msg) {
        //runnable封装的message。 handler.post/view.post
        if (msg.callback != null) {//msg中的callback 优先级1
            handleCallback(msg);
        } else {
            if (mCallback != null) {
                //Handler(Callback callback)的时候,mCallback !=null
                if (mCallback.handleMessage(msg)) {//handler中的callback,优先级2
                    return;
                }
            }
            //正常的message那种形式,也即是new Handler时复写的方法。
            handleMessage(msg);// 优先级3
        }
    }

优先级:依次降低。

//封装成Message
private static Message getPostMessage(Runnable r) {
        Message m = Message.obtain();
        m.callback = r;
        return m;
    }
    
//分发调用
//注意:虽然时runnable,但是,并不是新的线程哈。Thread的start()方法才是开启了新的线程,此处的run()就是正常的方法。   
//Runnable中不要做耗时操作。
private static void handleCallback(Message message) {
        message.callback.run();
    }

退出:

public static void loop() {
        //死循环。唤醒/挂起?
        for (;;) {
            //next方法会阻塞线程,有消息就取出,没消息就等待。
            Message msg = queue.next();
            if (msg == null) {
                // No message indicates that the message queue is quitting.
                return;
            }
            msg.target.dispatchMessage(msg);
        }
    }

loop()是一个死循环,唯一跳出来的办法是消息队列的next方法返回null。否则,next方法会有消息就唤醒,取出msg分发,没消息就阻塞等待。

分发机制

图解


一个线程中的handler发送的消息,会不会跑到另外线程的MessageQueue队列中?

不会的,线程,Looper,队列三者一一对应。

一个线程间的多个handler发送消息,机制是怎样的?

这多个handler发送的消息会在同一个消息队列中,但是加入队列时"msg.target = this",会在Looper分发消息时" msg.target.dispatchMessage(msg)",分发到原来的handler中处理。

上一篇下一篇

猜你喜欢

热点阅读