2.消息事件分发

什么是消息机制,概述:

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
        }
    }

优先级:依次降低。

  • 优先级1:
    view.post(runnable)和handler.post(runnable)。最后runnable都会分装成Message。分发的时候,在第一处调用。
//封装成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();
    }
  • 优先级2:
    Handler(Callback callback)的时候,赋值,mCallback !=null。
    Callback的作用,源码中说明,就是用来创建一个Handler实例,但是并不需要派生Handler子类。提供了另外一种方式使用Handler。
    (不用派生Handler子类了,但是一样需要一个CallBack对象啊,并没有什么区别简化好嘛)。

  • 优先级3:
    就是那种常用的obtain一个Message,设置what,obj参数,发送的消息。

退出:

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分发,没消息就阻塞等待。

2.消息事件分发_第1张图片
分发机制

图解

  • Handler通过sendMessage()发送Message到MessageQueue队列;
  • Looper通过loop(),不断提取出达到触发条件的Message,并将Message交给target来处理;
  • 经过dispatchMessage()后,交回给Handler的handleMessage()或者runnable来进行相应地处理。

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

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

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

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

你可能感兴趣的:(2.消息事件分发)