Android 消息传递机制 - Looper/Handler/MessageQueue/Message 详解

目录

总览

Message

Obtain - 获取对象

Recycle

Asynchronous - 异步

MessageQueue

enqueueMessage函数详解

next函数详解

barrier详解

postSyncBarrier函数解读

removeSyncBarrier函数解读

IdleHandler解读

FileDescriptor介绍

Handler

dispatchMessage & handleMessage 函数详解

SendMessageXXX函数详解

RemoveMessage函数介绍

Looper

prepare函数详解 

loop函数详解

MainLooper


总览

画图工具:https://www.draw.io/ 

看完之后画个图,便于理解:

Message

官方文档:https://developer.android.com/reference/android/os/Message

Defines a message containing a description and arbitrary data object that can be sent to a Handler. This object contains two extra int fields and an extra object field that allow you to not do allocations in many cases.

While the constructor of Message is public, the best way to get one of these is to call Message.obtain() or one of the Handler.obtainMessage() methods, which will pull them from a pool of recycled objects.

虽然消息的构造函数是公共的,但构建消息对象的最佳方法是调用Message.obtain()或其中一个Handler.obtainMessage()方法,这将从消息池(链表)中获取已回收的消息对象。

Obtain - 获取对象

注意警告里的话,最好的构建消息的方式是调用Message.obtain(),或者Handler.obtainMessage() ,会复用已经回收的消息。

所有的Message构造函数最终都会调用obtain()函数,我们来看看源码:

注意:从全局的消息链表返回一个消息体,避免经常去new一个新的实例。(这个有可能会造成内存泄漏)

/**
 * Return a new Message instance from the global pool. Allows us to
 * avoid allocating new objects in many cases.
 * 
 * 从一个全局的池子里返回一个Message实例。让我们在各种情况下,避免去分配新的对象。
 */
public static Message obtain() {
    synchronized (sPoolSync) {
        // 如果sPool非等于null,则把sPool返回,m.next赋值给sPool,并减少sPoolSize
        if (sPool != null) {
            Message m = sPool;
            sPool = m.next;
            m.next = null;
            m.flags = 0; // clear in-use flag
            sPoolSize--;
            return m;
        }
    }
    // 如果sPool为null,则new一个message
    return new Message();
}

看到这里会有些困惑,sPool是什么鬼?next又是什么鬼???

我们继续往下看,recycleUnchecked()函数。

Recycle

/**
 * Recycles a Message that may be in-use.
 * Used internally by the MessageQueue and Looper when disposing of queued Messages.
 */
void recycleUnchecked() {
    // Mark the message as in use while it remains in the recycled object pool.
    // Clear out all other details.
    flags = FLAG_IN_USE;
    what = 0;
    arg1 = 0;
    arg2 = 0;
    obj = null;
    replyTo = null;
    sendingUid = -1;
    when = 0;
    target = null;
    callback = null;
    data = null;

    synchronized (sPoolSync) {
        // 把sPool赋值给next,把当前的消息对象赋值给了sPool。于是当有消息回收时,sPool就非等于null了。
        if (sPoolSize < MAX_POOL_SIZE) {
            next = sPool;
            sPool = this;
            sPoolSize++;
        }
    }
}

我们再看看这几个变量的定义:

// sometimes we store linked lists of these things
// 通过next成员变量简单实现LinkedList,而sPool是一个全局的消息实例,处于链表的最末端。
/*package*/ Message next;

private static final Object sPoolSync = new Object();
private static Message sPool;
private static int sPoolSize = 0;

// 链表(或者说消息池)的最大size是50。
private static final int MAX_POOL_SIZE = 50;

Asynchronous - 异步

ChoreographerpostCallbackDelayedInternal()函数里,看到msg.setAsynchronous(true);这样一行代码。

说实话,当时我的是懵逼的,根本不知道Message还分同步和异步。

首先我们还是来看源码&注解肯定会有疑惑,请继续看下一章:MessageQueue

/**
 * Sets whether the message is asynchronous, meaning that it is not
 * subject to {@link Looper} synchronization barriers.
 * <p>
 * Certain operations, such as view invalidation, may introduce synchronization
 * barriers into the {@link Looper}'s message queue to prevent subsequent messages
 * from being delivered until some condition is met.  In the case of view invalidation,
 * messages which are posted after a call to {@link android.view.View#invalidate}
 * are suspended by means of a synchronization barrier until the next frame is
 * ready to be drawn.  The synchronization barrier ensures that the invalidation
 * request is completely handled before resuming.
 * </p><p>
 * Asynchronous messages are exempt from synchronization barriers.  They typically
 * represent interrupts, input events, and other signals that must be handled independently
 * even while other work has been suspended.
 * </p><p>
 * Note that asynchronous messages may be delivered out of order with respect to
 * synchronous messages although they are always delivered in order among themselves.
 * If the relative order of these messages matters then they probably should not be
 * asynchronous in the first place.  Use with caution.
 * </p>
 *
 * @param async True if the message is asynchronous.
 *
 * @see #isAsynchronous()

 * 设置消息是否是异步的,这意味着它不受Looper同步消息拦截器(barriers)的影响。
 *
 * 某些操作(例如视图失效),可能会在Looper的MessageQueue引入同步拦截器,用来阻碍后续同步消息的分发,直到某些情况的出现。
 *
 * 在视图失效的情况下,调用invalidate后分发的消息,会被同步拦截器suspend,直到下一帧准备好了为止。
 *
 * 同步拦截器确保invalidation请求在恢复之前会被完全处理。    
 *
 * 异步消息不受同步拦截器的影响。他们通常表示必须独立处理的中断,输入事件和其他信号,即使其他工作已暂停。
 * 
 * 请注意,异步消息可能无序传递,同步消息虽然它们总是按顺序分发。      

 * 如果这些消息的顺序很重要,那么首先它们可能不应该是异步的。

 * 谨慎使用异步。  
 */
public void setAsynchronous(bool
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值