什么是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什么是Handler的同步屏障机制?,android适配器模式
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 (;

上一篇:7年老Android收到阿里offer,跟领导提离职被怼:为年薪百万不做兄弟


下一篇:获取window窗口大小