Handler related learning (three) handler must be back

Android-Handler synchronization barrier

https://www.jianshu.com/p/2fb96d4e0cd5

1. The synchronization barrier of the message mechanism

After the Handler sets the synchronization barrier, it can intercept Looper's acquisition and distribution of synchronization messages. After joining the synchronization barrier, Looper will only obtain and process asynchronous messages. If there is no asynchronous message, it will enter the blocking state.

The synchronization barrier of the message mechanism is actually blocking the synchronization message and only letting the asynchronous message pass. The way to open the synchronization barrier is to call the following method:

MessageQueue#postSyncBarrier()

The source code for creating a synchronization message is as follows:

@TestApi
public int postSyncBarrier() {
    // 这里传入的时间是从开机到现在的时间戳
    return postSyncBarrier(SystemClock.uptimeMillis());
}
/**
 * 这就是创建的同步屏障的方法
 * 同步屏障就是一个同步消息,只不过这个消息的target为null
 */
private int postSyncBarrier(long when) {
    // Enqueue a new sync barrier token.
    // We don't need to wake the queue because the purpose of a barrier is to stall it.
    synchronized (this) {
        final int token = mNextBarrierToken++;
        // 从消息池中获取Message
        final Message msg = Message.obtain();
        msg.markInUse();
        // 初始化Message对象的时候,并没有给Message.target赋值,
        // 因此Message.target==null
        msg.when = when;
        msg.arg1 = token;

        Message prev = null;
        Message p = mMessages;
        if (when != 0) {
            // 这里的when是要加入的Message的时间
            // 这里遍历是找到Message要加入的位置
            while (p != null && p.when <= when) {
                // 如果开启同步屏障的时间(假设记为T)T不为0,且当前的同步
                // 消息里有时间小于T,则prev也不为null
                prev = p;
                p = p.next;
            }
        }
        // 根据prev是否为null,将msg按照时间顺序插入到消息队列的合适位置
        if (prev != null) { // invariant: p == prev.next
            msg.next = p;
            prev.next = msg;
        } else {
            msg.next = p;
            mMessages = msg;
        }
        return token;
    }
}

You can see here that the target is not assigned a value when the Message object is initialized, so the source of target==null can be found. In this way, a target==null message can be inserted, which is a synchronization barrier.
So after opening the message barrier, how are the so-called asynchronous messages handled?
The final processing of the message is actually in the message poller Looper#loop(), and MessageQueue#next() is called in the loop() loop to fetch the message from the message queue.

In the next method of MessageQueue.java:

In the while, it is first judged that this msg is a synchronous message, !msg.isAsynchronous(), if the message is synchronous, the next msg is executed.

From the above MessageQueue.next method, it can be seen that when the message queue opens the synchronization barrier (that is, the identifier is msg.target==null), the message mechanism will give priority to asynchronous messages when processing messages. In this way, the synchronization barrier plays a role of filtering and priority

As shown in the figure above, there are synchronous and asynchronous messages (yellow part) and a wall (synchronous barrier-red part) in the message queue. With the existence of the synchronization barrier, the two asynchronous messages msg_2 and msg_M can be processed first, while the subsequent synchronous messages such as msg_3 will not be processed. So when can these synchronization messages be processed? You need to remove this synchronization barrier first, that is, call MessageQueue#removeSyncBarrier()

How to send asynchronous messages
Usually when we use Handler to send messages, these messages are all synchronous messages. If we want to send asynchronous messages, then use one of the following constructors when creating Handler (async passes true)

public Handler(boolean async);
public Handler(Callback callback, boolean async);
public Handler(Looper looper, Callback callback, boolean async);

Then all messages sent through the Handler will become asynchronous messages

 

 

 

 

 

 

 

 

 

 

 

 

 

Guess you like

Origin blog.csdn.net/cpcpcp123/article/details/115261890