View.post()不靠谱的地方你知道多少

源代码 2024-9-15 17:15:01 56 0 来自 中国
首先我们来看一段代码:
1.png 启动了两个模仿器 API 22 和API 26分别是安卓7.0以下和安卓7.0以上
2.png 下面我们就从源码分析他们之间的差别以及为啥造成的征象差别
首先我们来分析安卓7.0以下的源码流程:




当attachInfo为空时走的是ViewRootImpl.getRunQueue().post(action);代码  当attachInfo不为空时,API26上下没区别。
ViewRootImpl可以明白是一个Activity的ViewTree的根节点的实例。每个ViewRootImpl就是用来管理DecorView和ViewTree。
ViewRootImpl的用来承载Runnable的队列是sRunQueues,它是一个静态变量,也就是说在APP的生命周期内,ViewRootImpl中的消息队列就是这一个。
我们再来看看前面提到的ViewRootImpl.getRunQueue.post()到底干了什么?


接下来我们再看哪里消耗mActions内里的Runnable


6.png 继承看executeActions在哪调用的


可以发现android.view.ViewRootImpl#performTraversals调用到的,而performTraversals()又是在android.view.ViewRootImpl#doTraversal调用的,它又是在
在TraversalRunnable中实行,
9.png 以是在API23以下,executeAction() 是会被循环调用,根本上其内的mActions只要有未实行的Runnable立即就会被消耗掉。
以是在API23以下的装备上,View.post根本上是靠谱的,post出去的都是偶然机实行的。
接下来分析API24的实现细节


同样类似的和API24以下,关键看下executeActions在哪实行,直接按住ctrl加上鼠标左键单击


既然executeActions()方法,在API24以上,只有在dispatchAttachedToWindow() 方法中,才偶然机被调用到,而View.dispatchAttachedToWindow()方法,只有在View通过 addView()等方法中到场到一个ViewGroup的时间,才会被调用到,这就导致直接写在Layout 布局中的控件没有被addView的话,那么它永久也不会实行。这就导致征象不一致的缘故。
留意:上述都是分析的是 mAttachInfo 已经为空的情况,不为空是没有区别的。
可以只管制止使用View.post()方法,直接使用Handler.post方法来更换。
您需要登录后才可以回帖 登录 | 立即注册

Powered by CangBaoKu v1.0 小黑屋藏宝库It社区( 冀ICP备14008649号 )

GMT+8, 2024-10-18 22:36, Processed in 0.131006 second(s), 35 queries.© 2003-2025 cbk Team.

快速回复 返回顶部 返回列表