27道 Handler 经典面试题,你能答出多少,涨薪7K

        }

    }

    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`方法之后,还偷偷做了一个操作——`recycleUnchecked`。



public static void loop() {

    for (;;) {

        Message msg = queue.next(); // might block



        try {

            msg.target.dispatchMessage(msg);

        } 



        msg.recycleUnchecked();

    }

}

//Message.java

private static Message sPool;

private static final int MAX_POOL_SIZE = 50;



void recycleUnchecked() {

    flags = FLAG_IN_USE;

    what = 0;

    arg1 = 0;

    arg2 = 0;

    obj = null;

    replyTo = null;

    sendingUid = UID_NONE;

    workSourceUid = UID_NONE;

    when = 0;

    target = null;

    callback = null;

    data = null;



    synchronized (sPoolSync) {

        if (sPoolSize < MAX_POOL_SIZE) {

            next = sPool;

            sPool = this;

            sPoolSize++;

        }

    }

} 



在`recycleUnchecked`方法中,释放了所有资源,然后将当前的空消息
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值