直播平台源码,信息的双端同步处理
直播平台源码,信息的双端同步处理
Handler组件中包含:Looper、Message、MessageQueue、Handler。
在Message中,有一个变量flag,用于标记这个Message正在被使用、此消息是异步消息等,通过一个方法isAsynchronous()可以获取当前Message是否为异步消息。同时,在Message中有一个变量target,是Handler类型的,表示最终由这个Handler进行处理。
平时我们发送消息时,这个target是不可以为null的。
//MessageQueue.java
boolean enqueueMessage(Message msg, long when) {
if (msg.target == null) {
throw new IllegalArgumentException("Message must have a target.");
}
if (msg.isInUse()) {
throw new IllegalStateException(msg + " This message is already in use.");
}
}
但是在发送屏障消息的时候,target是可以为空的,它本身仅仅是起屏蔽普通消息的作用,所以不需要target。MessageQueue中提供了postSyncBarrier()方法用于插入屏障消息。
//MessageQueue.java
/**
* @hide
*/
public int postSyncBarrier() {
return postSyncBarrier(SystemClock.uptimeMillis());
}
private int postSyncBarrier(long when) {
synchronized (this) {
//这个token在移除屏障时会使用到
final int token = mNextBarrierToken++;
final Message msg = Message.obtain();
msg.markInUse();
msg.when = when;
msg.arg1 = token;
//在屏障的时间到来之前的普通消息,不会被屏蔽
Message prev = null;
Message p = mMessages;
if (when != 0) {
while (p != null && p.when <= when) {
prev = p;
p = p.next;
}
}
//插入到单链表中
if (prev != null) { // invariant: p == prev.next
msg.next = p;
prev.next = msg;
} else {
msg.next = p;
mMessages = msg;
}
return token;
}
}
看起来比较简单,可以获取的信息如下:
屏障消息和普通消息区别在于屏幕没有target,普通消息有target是因为它需要将消息分发给对应的target,而屏幕不需要被分发,它就是用来挡住普通消息来保证异步消息优先处理的
屏障和普通消息一样可以根据时间来插入到消息队列中的适当位置,并且只会挡住它后面的同步消息的分发
postSyncBarrier会返回一个token,利用这个token可以撤销屏障
postSyncBarrier是hide的,使用它得用反射
插入普通消息会唤醒消息对了,但插入屏障不会
现在屏障已经插入到消息队列中了,它是如何挡住普通消息而只需要异步消息进行执行的呢?Looper是通过MessageQueue的next方法来获取消息的,来看看
//MessageQueue.java
Message next() {
...
int pendingIdleHandlerCount = -1;
int nextPollTimeoutMillis = 0;
for (;;) {
//如有消息被插入到消息队列或者超时时间到,就被唤醒,否则会阻塞在这里
nativePollOnce(ptr, nextPollTimeoutMillis);
synchronized (this) {
final long now = SystemClock.uptimeMillis();
Message prevMsg = null;
Message msg = mMessages;
//遇到屏障 它的target是空的
if (msg != null && msg.target == null) {
//找出屏障后面的异步消息,
do {
prevMsg = msg;
msg = msg.next;
//isAsynchronous()返回true才是异步消息
} while (msg != null && !msg.isAsynchronous());
}
//如果找到了异步消息
if (msg != null) {
if (now < msg.when) {
//还没到处理时间,再等一会儿
nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
} else {
//到处理时间了,就从链表中移除,返回这个消息
mBlocked = false;
if (prevMsg != null) {
prevMsg.next = msg.next;
} else {
mMessages = msg.next;
}
msg.next = null;
msg.markInUse();
return msg;
}
} else {
//如果没有异步消息就一直休眠,等待被唤醒
nextPollTimeoutMillis = -1;
}
...
}
...
}
}
以上就是直播平台源码,信息的双端同步处理, 更多内容欢迎关注之后的文章