[聚合文章] Android消息处理机制

消息系统 1900-01-01 19 阅读

消息处理机制

相关类

  • Message:消息,其中包含了消息ID,处理对象和处理数据,由MessageQueue统一队列管理,最终由Handler处理。
  • Handler:负责Message发送和处理。
  • MessageQueue:消息队列,按照FIFO原则存放消息。
  • Looper:消息泵,来处理MessageQueue中的Message。
Message,MessageQueue,Handler,Looper之间的关系
aed1213f-a5c1-4d65-b308-b807ca1c3fc1.jpeg

看代码

Looper.class
变量
/*** 用于管理Looper*/static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();/*** 持有主线程Looper*/private static Looper sMainLooper; // guarded by Looper.class/*** 每个Looper持有一个消息队列*/final MessageQueue mQueue;/*** 每个Looper持有一个线程*/final Thread mThread;
方法
/** * 创建一个Looper */public static void prepare() {    prepare(true);}/** * 真实的创建Looper的方法 * @param quitAllowed */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));}/** * 初始化一个主线程的Looper,只能创建一个在启动应用的时候已经调用并创建。所以不需要我们自己去创建,否则会抛出异常。 */public static void prepareMainLooper() {    prepare(false);    synchronized (Looper.class) {        if (sMainLooper != null) {            throw new IllegalStateException("The main Looper has already been prepared.");        }        sMainLooper = myLooper();    }}/** * 返回一个主线程的上的Looper */public static Looper getMainLooper() {    synchronized (Looper.class) {        return sMainLooper;    }}/** * 进行消息循环,获取消息,发送消息 */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);        ......    }}/** * 返回一个当前线程中的Looper * @return */public static @Nullable Looper myLooper() {    return sThreadLocal.get();}/** * 返回消息队列 * @return */public static @NonNull MessageQueue myQueue() {    return myLooper().mQueue;}private Looper(boolean quitAllowed) {    mQueue = new MessageQueue(quitAllowed);    mThread = Thread.currentThread();}/** * 判断当前线程是否和Looper的线程相同 * @return */public boolean isCurrentThread() {    return Thread.currentThread() == mThread;}
MessageQueue.class
 /** * 消息入队列,按时顺序进行排序存储 * * @param msg 消息实体 * @param when 消息发送时间 * @return * */boolean enqueueMessage(Message msg, long when) {    ......    synchronized (this) {        .....        msg.markInUse();        msg.when = when;        Message p = mMessages;        boolean needWake;        if (p == null || when == 0 || when < p.when) {            /**             * 把消息放到消息队列的头上,需要唤醒             */            msg.next = p;            mMessages = msg;            needWake = mBlocked;        } else {            /**             * 把消息插入到合适的位置             */            needWake = mBlocked && p.target == null && msg.isAsynchronous();            Message prev;            for (;;) {                prev = p;                p = p.next;                if (p == null || when < p.when) {                    break;                }                if (needWake && p.isAsynchronous()) {                    //说明即便msg是异步的,也不是链表中第一个异步消息,所以没必要唤醒了                    needWake = false;                }            }            msg.next = p; // invariant: p == prev.next            prev.next = msg;        }        // We can assume mPtr != 0 because mQuitting is false.        if (needWake) {            nativeWake(mPtr);        }    }    return true;}

这里有个syncBarrier(同步分割栏)但是对其操作都是@hide,使用还还需要用java反射机制。
barrier的作用就是在某个时间阻拦不是异步的消息,如果需要继续获取消息必须把这个barrier给remove掉。

Message.class
/*** 消息实体的唯一标示*/public int what;/*** 消息实体参数*/public int arg1;/*** 消息实体参数*/public int arg2;/*** 消息实体中的存储对象*/public Object obj;/*** 发送时间*//*package*/ long when;/*** 消息实体中所带的数据*//*package*/ Bundle data;/*** 处理对象*//*package*/ Handler target;/*** 回调方法*//*package*/ Runnable callback;/*** 消息对象池*/private static Message sPool;/*** 消息对象个数*/private static int sPoolSize = 0;/*** 默认最大个数为50*/private static final int MAX_POOL_SIZE = 50;

Message不能通过new创建对象应该通过obtain方法获取Message对象,因为为了避免大量的创建Message对象,Message会通过自身维护的一个对象池取Message对象。

obtain方法
  • public static Message obtain()
  • public static Message obtain(Message orig)
  • public static Message obtain(Handler h)
  • public static Message obtain(Handler h, Runnable callback)
  • public static Message obtain(Handler h, int what)
  • public static Message obtain(Handler h, int what, Object obj)
  • public static Message obtain(Handler h, int what, int arg1, int arg2)
  • public static Message obtain(Handler h, int what, int arg1, int arg2, Object obj)
设置处理者
  • public void setTarget(Handler target)
发送消息给处理者
  • public void sendToTarget()
处理捆绑数据
  • public Bundle getData()
  • public Bundle peekData()
  • public void setData(Bundle data)
Handler.class
/** * 处理消息接口 */public interface Callback {    public boolean handleMessage(Message msg);}/** * 实现这个方法处理消息 */public void handleMessage(Message msg) {}/** * 这个是当mssage.callback不会空的时候执行 * @param message */private static void handleCallback(Message message) {    message.callback.run();}/** * 由Looper在获取消息后调用,这里是处理消息的逻辑 */public void dispatchMessage(Message msg) {    if (msg.callback != null) {        /**        * 如果message中没有callback函数,就直接执行handler中的静态方法handleMessage        */        handleCallback(msg);    } else {        /**        * 如果Handler中定义了mCallback,那么先去执行mCallBack中的内容。        * 如果mCallback返回true,说明被mCallback中的handleMessage处理完成不在需要后续的Handler中的handleMessage处理        * 如果mCallback返回false,说明mCallback中的handleMessage没有处理完消息,后续有Handler中的handleMessage继续处理        */        if (mCallback != null) {            if (mCallback.handleMessage(msg)) {                return;            }        }        handleMessage(msg);    }}

这里有两个handleCallback,一个是静态的方法,一个是普通方法;在调用的时机不一样,静态方法是在Message中定义了callback的时候调用的。

dispatchMessage()方法的处理消息逻辑

  • 第一步:如果message中没有callback函数,就直接执行handler中的静态方法handleMessage
  • 第二步:如果Handler中定义了mCallback,那么先去执行mCallBack中的内容。
  • 第三步:如果mCallback返回true,说明被mCallback中的handleMessage处理完成不在需要后续的Handler中的handleMessage处理
    -第四步:如果mCallback返回false,说明mCallback中的handleMessage没有处理完消息,后续有Handler中的handleMessage继续处理
相对应Message中获取Message对象的方法
  • public final Message obtainMessage()
  • public final Message obtainMessage(int what)
  • public final Message obtainMessage(int what, Object obj)
  • public final Message obtainMessage(int what, int arg1, int arg2)
  • public final Message obtainMessage(int what, int arg1, int arg2, Object obj)
用Runnable接收消息,这里的Runnable和线程中的Runable不一样只是一个普通的方法,运行在当前线程中。
  • public final boolean post(Runnable r)
  • public final boolean postAtTime(Runnable r, long uptimeMillis)
  • public final boolean postAtTime(Runnable r, Object token, long uptimeMillis)
  • public final boolean postDelayed(Runnable r, long delayMillis)
  • public final boolean postAtFrontOfQueue(Runnable r)
直接发送消息
  • public final boolean sendMessage(Message msg)
  • public final boolean sendEmptyMessage(int what)
  • public final boolean sendEmptyMessageDelayed(int what, long delayMillis)
  • public final boolean sendEmptyMessageAtTime(int what, long uptimeMillis)
  • public final boolean sendMessageDelayed(Message msg, long delayMillis)
  • public boolean sendMessageAtTime(Message msg, long uptimeMillis)
  • public final boolean sendMessageAtFrontOfQueue(Message msg)

注:本文内容来自互联网,旨在为开发者提供分享、交流的平台。如有涉及文章版权等事宜,请你联系站长进行处理。