微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

什么是Handler的同步屏障机制?,android适配器模式

正常插入消息会调用enqueueMessage方法同时将handler赋值给message的target。

//将消息插入消息队列

private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg,

long uptimeMillis) {

msg.target = this;

msg.workSourceUid = ThreadLocalWorkSource.getUid();

//进行判断是否将消息设置为异步消息

if (mAsynchronous) {

msg.setAsynchronous(true);

}

return queue.enqueueMessage(msg, uptimeMillis);

}

在MessageQueue中进行判断,如果target为空也就是这个message没有对应的handler则会报异常。

boolean enqueueMessage(Messag


e 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.");

}

// 如果需要唤醒,则唤醒

if (needWake) {

nativeWake(mPtr);

}

通过MessageQueue的postSyncBarrier方法插入屏障,message的target属性为null

private int postSyncBarrier(long when) {

synchronized (this) {

final int token = mNextBarrierToken++;

//msg没有为target属性赋值

final Message msg = Message.obtain();

//根据时间插入到MessageQueue中

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指向的handler处理

  • 屏障消息会插入到MessageQueue中合适的位置,这个消息以后的普通消息将被屏蔽

  • postSyncBarrier返回一个int类型的数值,通过这个数值可以撤销屏障

  • postSyncBarrier方法是私有的,如果我们想调用它就得使用反射

  • 插入普通消息会唤醒消息队列,但是插入屏障不会

如何发送异步消息

通常我们发送的都是普通消息,如果想发送异步消息

  • 可以在创建handler时使用如下的构造器中的一种,同时将async参数设置为true,这样这个handler发送的消息就都是异步消息了。

public Handler(boolean async) {

this(null, async);

}

public Handler(@NonNull Looper looper, @Nullable Callback callback) {

this(looper, callback, false);

}

public Handler(@Nullable Callback callback, boolean async) {

mLooper = Looper.myLooper();

if (mLooper == null) {

throw new RuntimeException(

"Can’t create handler inside thread " + Thread.currentThread()

  • " that has not called Looper.prepare()");

}

mQueue = mLooper.mQueue;

mCallback = callback;

mAsynchronous = async;

}

  • 除了这种方式还可以直接设置消息的类型为异步消息

public void setAsynchronous(boolean async) {

if (async) {

flags |= FLAG_ASYNCHRONOUS;

} else {

flags &= ~FLAG_ASYNCHRONOUS;

}

}

消息处理的过程

MessageQueue是通过next方法来遍历消息的

@UnsupportedAppUsage

Message next() {

for (;

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐