Android MessageQueue 源码笔记

79 篇文章 0 订阅
36 篇文章 0 订阅
  1. MessageQueue:

    • 一个用于存储Looper要dispatch的Message的底层容器, 不过其功能要远远超过这个注释的描述.
  2. Message mMessages:

    • 以链表的形式来保存Messge,这里的mMessages是当前队列的第一个要dispatch的Message,后面的通过Message本身的next来进行连接
  3. interface IdleHandler:

    • 其概念是一种连带处理,在当前的thread已经将自己应该执行的task(不包括没有到时的Task**)全部执行完,将要block的等待更多Message到来的时候**, 这个callback会被调用.
    • 其函数queueIdle()return true则会保留这个IdleHandler,return false则会移除这个IdleHandler.
    • addIdleHandler(IdleHandler handler)会将非null的hanlder加入到mIdleHandlers中(有同步,可见该函数的调用可能是多线程的)
    • removeIdleHandler(IdleHandler handler)不解释.
  4. 构造函数: MessageQueue(boolean quitAllowed):

    • 设置mQuitAllowed
    • mPtr = nativeInit(): 在native层也要进行初始化,并且会返回native对象在native层的指针值.
  5. dispose(): 只能在 messageQueue所属的looper所在的线程或者finalizer调用.

    • nativeDestroy(mPtr);释放native层的资源
    • mPtr = 0来防止重复dispose()
  6. Message next(), 最重要的函数,Looper即是通过调用此函数来不断的从MessageQueue中取出Message进行处理:

    • pendingIdleHandlerCount = -1,
    • nextPollTimeoutMillis = 0
    • native**Poll**Once(mPtr, nextPollTimeoutMillis), 调用此方法来同步阻塞的等待IO到来 + 超时参数, 读应的native方法是pollOnce(…) -> native层的Looper的pollOnce() -> pollInner(…) -> epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis), 可见最后是调用了高性能的epoll_wait(…)这种IO复用的调用, 任何对mEpollFd进行的IO操作都会使此方法结束阻塞等待并返回
    • 因为addMessage这个操作是会被多线程调用的, 因此有关mMessages这个链表的操作需要同步.
    • 获取当前时间 now.
    • 如果当前的msg的target == null, 那么说明是一个barrier(而非一个真正的message, barrier也是一个特殊的message),这种情况下sync的message都被stall了,而async的则不受影响,沿着当前msg链表遍历知道找到一个Async的message为止, 当然,如果不是barrier, 那么直接取出当前mMessages就可以,就是这次要处理的message.
      1. 如果当前要处理的Message是null: 那么nextPollTimeoutMillis = -1
      2. 如果当前要处理的Message不是null:
        • 如果now < msg.when, 说明还没有到处理这个msg的时间,还需要等待: nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE)
        • 否则已经到了处理这个Msg的时机了, mBlocked = false; mBlocked代表的意思是表示是否next()会阻塞在等待pollOnce()这个函数的返回
        • 下一步就是更新Message链表, 考虑msg是header和不是header的情况,包括了msg的next = null来将msg切断与message链表的联系。
        • msg.markInUse()表明其当前正在被使用.
      3. 如果没有得到非null的要处理的Message(也没有pollOnce()继续等待), 那么会检查mQuitting,如果是,那么调用dispose(), 返回null, Looper.loop()在MessageQueue的next()返回null时也会结束自己的loop方法,从而整个HandlerThread结束(无限消息循环处理已经结束), 这里需要Quitting这个标志位的原因是不一定没有的到要处理的Message就一定要结束, 很可能之前已经把所有的Message已经全部处理完了
      4. 如果也没有quitting, 而也没有Message要处理的,那么就会考虑IdleHandler了,只有在当前MessageQueue是empty或者当前第一个Message的处理时间还没有到的情况下才会考虑。
      5. 如果也没有要做的IdleHandler,那么mBlocked = true, continue来继续阻塞等待将来的Message.
      6. 否则下一步会执行Idlehandler的操作, 一个细节是,因为IdleHandler本身的add/remove是有可能多线程调用的,但是如果在整个IdleHandler数组遍历回调的过程中都同步,会带来极大的性能损耗,因此这里会先将IdleHandler数组拷贝(这样就算其他线程把这个数组改变了,也不会影响当前的Idle callback)一遍,然后不带同步的进行调用即可
      7. 遍历IdleJHandler的过程中,如果Idler的queueIdle()返回false,那么会将其从Idler数组中remove,可以看做一次one-shot的callback
      8. 在Idler都成功处理玩以后,会将nextPollTimeoutMillis = 0来将下次poll等待Message的超时设置为0即不等待,因为很有可能在处理Idler这段时间,其他线程已经post来了新的Message
  7. quit(boolean safe):

    • safe的含义不赘述了.
    • 如果!mQuitAllowed, 那么直接抛异常,估计也只有Main thread是禁止quit的.
    • 因为下面会操作mQuitting和Message链表,因此下面的操作需要进行同步,因为quit()可能在其他线程被调用.
    • mQuitting = true; 显然这个标识位必须是true
    • 如果safe->removeAllFutureMessagesLocked(), 否则removeAllMessagesLocked()
    • 最后会调用nativeWake(mPtr)来唤醒next()方法(如果是通过nativePollOnce()在waiting的话, 如果不是waiting,也会因为之前已经将所有的Message remove以及不能再post Message的原因而最终走到next()中判断mQuitting的逻辑,从而next()返回null来结束loop())
  8. enqueueSyncBarrier(long when):

    • 其实就是插入一个target为null的Message, 复杂的逻辑在于要遍历当前的Message链表,将这个BarrierMessage插入到一个合适的位置,最后返回mNextBarrierToken++作为此Barrier的Token留待remove时用.
    • 插入这个Message不需要进行wake nativePollOnce(), 因为本意就是使其中的Sync Message等待,不必多次一举
  9. removeSyncBarrier(int token):

    • 本质也是一个搜索+删除的链表操作.
    • 不过remove barrer**可能需要wake当前等待的next(),因为barrier被拿掉了**
    • 最后如果确认是需要wake的,并且当前也没有Quitting,那么会调用 nativeWake(mPtr).
  10. nativeWake(mPtr):

    • nativeWake(mPtr) -> MessageQueue.cpp的wake()->Looper.cpp的wake() -> write(mWakeWritePipeFd, “W”, 1); 向FD写入一个数据(“W”)来唤醒之前的epoll_wait()
  11. enqueueMessage(Message msg, long when):

    • 本质也是一个搜索+删除的链表操作.
    • 会在这个过程中判断是否需要Wake, 如果需要,最后会调用nativeWake(mPtr).
  12. 各种形式的removeMessages(….)

    • 搜索+删除的链表操作.
  13. 各种形式的hasMessages(…)

    • 搜索链表的操作.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值