安卓底朝天—— android.os.Handler.post::Runnable: 的调用栈

Handler 中可调用的函数有:

android.os.Handler.post::Runnable:
android.os.Handler.postAtTime::Runnable,long:
android.os.Handler.postAtTime::Runnable,Object,long:
android.os.Handler.postDelayed::Runnable,long:
android.os.Handler.postAtFrontOfQueue::Runnable:
android.os.Handler.sendMessage::Message:
android.os.Handler.sendEmptyMessage::int:
android.os.Handler.sendEmptyMessageDelayed::int,long:
android.os.Handler.sendEmptyMessageAtTime::int,long:
android.os.Handler.sendMessageDelayed::Message,long:
android.os.Handler.sendMessageAtTime::Message,long:
android.os.Handler.sendMessageAtFrontOfQueue::Message:

实际上,这些函数的里子是一样的,它们都调用了 enqueueMessage,看下图:
在这里插入图片描述
虽然这些函数有的接收一个 Runnable,有的接收一个 Message,但在实现中,Runnable 会变成 Message 的一个属性,从图中可以看出来,这是通过函数 getPostMessage 实现的,我们看一下函数的源码:

    private static Message getPostMessage(Runnable r) {
        Message m = Message.obtain();
        m.callback = r;
        return m;
    }

下面的图说明了你传入的 Runnable 是怎么传给属性 android.os.Message.callback 的。
在这里插入图片描述

因此无论你传入的是 Message 还是 Runnable,它都会存一个Message。

所有实际的工作是由函数:android.os.Handler.enqueueMessage::MessageQueue,Message,long: 做的,而它也只是把工作交给了函数:
android.os.MessageQueue.enqueueMessage::Message,long:,而且到这里 Handler 类已经没有东西了,除了下面这些我觉得不需要讲的:
android.os.Handler.obtainMessage:::
android.os.Handler.obtainMessage::int:
android.os.Handler.obtainMessage::int,Object:
android.os.Handler.obtainMessage::int,int,int:
android.os.Handler.obtainMessage::int,int,int,Object:
android.os.Handler.removeCallbacks::Runnable:
android.os.Handler.removeCallbacks::Runnable,Object:
android.os.Handler.removeMessages::int:
android.os.Handler.removeMessages::int,Object:
android.os.Handler.removeCallbacksAndMessages::Object:

函数 android.os.MessageQueue.enqueueMessage::Message,long:

将你传给的 message 存到了 Message 队列android.os.MessageQueue.mMessages 中,存的时候会按时间排序,而在函数 android.os.Looper.loop::: 中通过死循环不断的调用函数 android.os.MessageQueue.next::: 来从这个 Message 队列获取下一个 message,然调用函数 android.os.Handler.dispatchMessage::Message: 来处理消息。

函数 android.os.MessageQueue.next::: 里面也是个死循环,当消息队列中没有消息时,这个函数被函数 android.os.MessageQueue.nativePollOnce::long,int: 阻塞,当有消息但是队头的消息还没有到时间时,这个函数会在死循环中空转,一直等到第一个消息的时间到了的时候把这个消息返回。Handler 之所以可以延时执行,就是靠这个函数了。

函数 android.os.Handler.dispatchMessage::Message: 比较简单,可以直接上源码了:

    /**
     * Handle system messages here.
     */
    public void dispatchMessage(Message msg) {
        if (msg.callback != null) {
            handleCallback(msg);
        } else {
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            handleMessage(msg);
        }
    }

在这里插入图片描述

dispatchMessage 这个函数根据情况在三个函数中三选一调用:

android.os.Handler.handleCallback::Message: (这个函数调用了 Handler.post::Runnable: 传入的 Runnable)
android.os.Handler.Callback.handleMessage::Message:(这个我就不知道了)
android.os.Handler.handleMessage::Message: (这个函数调用了自定义的 Handler.handleMessage::Message:)

现在我们可以总结了调用栈了,拿函数 android.os.Handler.post::Runnable: 为例:

android.os.Handler.post::Runnable:
android.os.Handler.sendMessageDelayed::Message,long:
android.os.Handler.sendMessageAtTime::Message,long:
android.os.Handler.enqueueMessage::MessageQueue,Message,long:
android.os.MessageQueue.enqueueMessage::Message,long:
。。。。。。。。。。。。。。Message 被存入消息队列。。。。。。。。。。。。。。。。。。。
android.os.MessageQueue.mMessages
android.os.Looper.loop:::
。。。。。。。。。。。。。。从消息队列中按时间获取消息。。。。。。。。。。。。。。。。。。
android.os.MessageQueue.next:::
。。。。。。。。。。。。。。。。。处理获取到的消息。。。。。。。。。。。。。。。。。。。。
android.os.Handler.dispatchMessage::Message:
android.os.Handler.handleCallback::Message: / android.os.Handler.handleMessage::Message:

顺便说一下,Looper 是如何让不同线程中使用不同 Looper 实例的

它使用了属性 android.os.Looper.sThreadLocal,这是个 java.lang.ThreadLocal 类型的属性,源码:

    // sThreadLocal.get() will return null unless you've called prepare().
    static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();

当你想要得到一个 Looper 对象时,它调用了函数 java.lang.ThreadLocal.get:::,这个函数不论你在哪个线程调用,如果属性 sThreadLocal 存在于线程 A,它都会返回线程 A 中存放的实例。

因此在安卓开发中,你要在非 UI 线程更新 UI 的时候,Handler 对象必须是在 UI 线程获取的,因为 Handler 中有一个 Looper 类型的属性:android.os.Handler.mLooper,而 Loop 类有 MessageQueue 类型的属性,你存放消息的消息队列 MessageQueue 实例与 Looper 实例是一一对应的,下面这个图可以说明 enqueueMessage 函数存放消息的消息队列确实来自于 Looper 实例。
在这里插入图片描述
它能决定你 post 的 Runnable 或者 send 的 Message 存放在哪个 Looper 实例的 MessageQueue 中,也就是决定了你定义的回调函数在哪个 Looper 实例中运行,也就是决定了在哪个线程上运行。

再说一下Looper中消息队列和异步消息的理解

请你想像这样一个超市,超市里的顾客有毛病,非得按他们自己规定的时间结帐,如果因为前面顾客结帐时间太长而耽误了他们规定的结帐时间,对于顾客是可以接受的,但是时间不到,谁也不愿意结帐,这就是消息队列。
出于一种我也不知道为什么的原因,消息队列中有 barrier 的存在,它会阻塞队列的前进,但不会阻塞异步消息,这就是异步消息与同步消息的不同。
这些事情都是发生在函数 android.os.MessageQueue.next::: 中,想看实情的话可以去读这个函数的源码。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值