1.2 Handler机制

less than 1 minute read

Handler源码分析


    基础
    1. Message: 消息实体
    2. MessageQueue: 提供投递消息(MessageQueue#enqueueMessage), 和消费消息(MessageQueue#next)
    3. Handler: 向MessageQueue发送消息(#sendMessage), 和处理相应的消息(#handleMessage)
    4. Looper: 循环消息队列, 按分发机制讲消息分发给目标处理者

    流程
        1. Looper#prepare, 初始化Looper放到ThreadLocal
        2. Looper#loop, 读取MessageQueue的消息, 把Message分发给相应的target, 把消息放回消息池, 以便复用
        3. 消息分发机制, 当Message不为空, 调用Message#callback#run, 否则当Handler#mCallback不为空, 回调方法mCallback#handleMessage, 否则调用Handler#handleMessage
        4. 消息发送, Handler#sendMessageDelayed -> Handler#sendMessageAtTime -> Message#queueMessage
        5. MessageQueue#next, nativePollOnce是阻塞操作, 其中nextPollTimeoutMills代表下一个消息到来需要等待的时长, 当nativePollOnce返回时, next()从mMessage中提取一条消息
        6. MessageQueue#enqueueMessage, 队头消息是最早触发的消息, 当有消息插入时, 会从队列头开始遍历, 直到找到消息合适插入位置, 确保消息的时间顺序

    Handler(Native层)
        1. MessageQueue初始化, 创建Looper -> 创建epoll注册wait管道, 将唤醒事件(mWakeEventFd)添加到epoll实例, epoll_create/epoll_ctl
        2. nativePollOnce, MessageQueue#nativePollOnce -> Looper#pollOnce -> Looper#pollInner -> epoll_wait; 1. 调用epoll_wait阻塞方法, 用于等待事件发生或者超时, 2. epoll_wait返回: POOL_ERROR, 发生错误, 直接跳转到Done; POLL_TIMEOUT, 超时跳转到Done; 检测到管道有事件 (1)如果是管道读端产生事件, 则直接读取管道的数据, (2)如果是其它事件, 则处理request并生成response, push到response数组
        3. nativeWait, 用于唤醒, 包括`enqueueMessage``quit`都会调用`nativeWake`, 向管道写入字符
        4. 先处理Native Message, 再处理Native Request最后处理Java Message

1.2.1 Handler机制, Looper#loop()为什么不会卡死

真正会卡死主线程的操作是在回调方法onCreate/onStart/onResume等操作时间过长,会导致掉帧,甚至发生ANR,looper.loop本身不会导致应用卡死。looper.loop会消耗cpu, 但不会卡死, 另外它也不是无休止地循环, 而是有消息才会循环

1.2.2 Handler退出

调用Looper#quit - > MessageQueeu#quit, 唤醒线程返回null的msg, MessageQueue返回空msg即退出

参考