27道 Handler 经典面试题,你能答出多少?

好了,确实这个字段就表示是否阻塞的意思,再去看看enqueueMessage方法中,唤醒机制:

boolean enqueueMessage(Message msg, long when) {

synchronized (this) {

boolean needWake;

if (p == null || when == 0 || when < p.when) {

msg.next = p;

mMessages = msg;

needWake = mBlocked;

} else {

needWake = mBlocked && p.target == null && msg.isAsynchronous();

Message prev;

for (;😉 {

prev = p;

p = p.next;

if (p == null || when < p.when) {

break;

}

if (needWake && p.isAsynchronous()) {

needWake = false;

}

}

msg.next = p;

prev.next = msg;

}

if (needWake) {

nativeWake(mPtr);

}

}

return true;

}

  • 当链表为空或者时间小于表头消息时间,那么就插入表头,并且设置是否唤醒为mBlocked

再结合上述的例子,也就是当有新消息要插入表头了,这时候如果之前是阻塞状态(mBlocked=true),那么就要唤醒线程了。

  • 否则,就需要取链表中找到某个节点并插入消息,在这之前需要赋值needWake = mBlocked && p.target == null && msg.isAsynchronous()

也就是在插入消息之前,需要判断是否阻塞,并且表头是不是屏障消息,并且当前消息是不是异步消息。 也就是如果现在是同步屏障模式下,那么要插入的消息又刚好是异步消息,那就不用管插入消息问题了,直接唤醒线程,因为异步消息需要先执行。

  • 最后一点,是在循环里,如果发现之前就存在异步消息,那就还是设置是否唤醒为false

意思就是,如果之前有异步消息了,那肯定之前就唤醒过了,这时候就不需要再次唤醒了。

最后根据needWake的值,决定是否调用nativeWake方法唤醒next()方法。

[](()8、同步屏障和异步消息是怎么实现的?


其实在Handler机制中,有三种消息类型:

  • 同步消息。也就是普通的消息。

  • 异步消息。通过setAsynchronous(true)设置的消息。

  • 同步屏障消息。通过postSyncBarrier方法添加的消息,特点是target为空,也就是没有对应的handler。

这三者之间的关系如何呢?

  • 正常情况下,同步消息和异步消息都是正常被处理,也就是根据时间when来取消息,处理消息。

  • 当遇到同步屏障消息的时候,就开始从消息队列里面去找异步消息,找到了再根据时间决定阻塞还是返回消息。

Message msg = mMessages;

if (msg != null && msg.target == null) {

do {

prevMsg = msg;

msg = msg.next;

} while (msg != null && !msg.isAsynchronous());

}

也就是说同步屏障消息不会被返回,他只是一个标志,一个工具,遇到它就代表要去先行处理异步消息了。

所以同步屏障和异步消息的存在的意义就在于有些消息需要“加急处理”

[](()9、同步屏障和异步消息有具体的使用场景吗?


使用场景就很多了,比如绘制方法scheduleTraversals

void scheduleTraversals() {

if (!mTraversalScheduled) {

mTraversalScheduled = true;

// 同步屏障,阻塞所有的同步消息

mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();

// 通过 Choreographer 发送绘制任务

mChoreographer.postCallback(

Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);

}

}

Message msg = mHandler.obtainMessage(MSG_DO_SCHEDULE_CALLBACK, action);

msg.arg1 = callbackType;

msg.setAsynchronous(true);

mHandler.sendMessageAtTime(msg, dueTime);

在该方法中加入了同步屏障,后续加入一个异步消息MSG_DO_SCHEDULE_CALLBACK,最后会执行到FrameDisplayEventReceiver,用于申请VSYNC信号。

[](()10、Message消息被分发之后会怎么处理?消息怎么复用的?


再看看loop方法,在消息被分发之后,也就是执行了dispatchMessage方法之后,还偷偷做了一个操作——recycleU

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值