使用View.post()需要注意什么-创新互联
这篇文章给大家分享的是有关使用View.post()需要注意什么的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。
成都创新互联专注于溆浦企业网站建设,响应式网站建设,成都商城网站开发。溆浦网站建设公司,为溆浦等地区提供建站服务。全流程按需搭建网站,专业设计,全程项目跟踪,成都创新互联专业和态度为您提供的服务一、前言
有时候,我们会需要用到 View.post()
方法,来将一个 Runnable 发送到主线程去执行。这一切,看似很美好,它最终会通过一个 Handler.post()
方法去执行,又避免我们重新定义一个 Handler 对象。
但是,从 Android 7.0(Api level 24) 开始,View.post() 将不再那么靠谱了,你 post() 出去的 Runnable ,可能永远也不会有机会执行到。
二、post 在 7.0 的差异
2.1 post 方法的差异
前面提到,这个问题只出现在 Android 7.0 上。那么就先从源码分析 Android 7.0 到底对 View.post() 做了什么改动。
用 Diff 看一下它们的差异,左边是 Api Level 24+(以下简称 Api24) 的代码,右边是 Api level 23-(以下简称 Api23) 的代码。
很明显的可以看出来,它们只有在 mAttachInfo
为 null 的时候,执行的逻辑才会有差异。
Api24 中,会调用 getRunQueue().post(action)
,而 Api23 会调用 ViewRootImpl.getRunQueue().post(action)
方法,他们的差异就在这里。
2.2 Api23 post 的细节
先简单理解一下,ViewRootImpl
是什么。
ViewRootImpl
可以理解是一个 Activity 的 ViewTree 的根节点的实例。每个 ViewRootImpl 就是用来管理 DecorView 和 ViewTree。
ViewRootImpl
中的用来承载 Runnable 的队列是 sRunQueues ,它一个静态的变量,也就是说在 App 的生命周期内,ViewRootImpl
中的这个消息队列都是同一个。
再来看看前面提到的 ViewRootImpl.getRunQueue().post()
到底干了什么?
post()
方法只是单纯的将它包装成一个 HandlerAction 对象,然后放入 mActions 这个 ArrayList 中。继续追查下去就需要知道 mActions 中添加的 HandlerAction 在何时被消费掉了。
消费 HandlerAction 的地方,是 executeActions()
方法。
它最终,还是调用的 handler.postDelayed()
,这没什么好说的,关键点在于 executeAction()
方法,是在什么时候被调用的。
executeAction()
是被 TraversalRunnable 调用 doTraversa()
,在doTraversa()
方法中,进行调用的。而 TraversalRunnable 又是通过 Choreographer.postCallBack()
去循环调用的。这个 Choreographer
通过 doScheduleCallback()
发送一个 MSG_DO_SCHEDULE_CALLBACK
类型的消息循环调用,间隔就是一个 VSync 的间隔。
关于 Choreographer ,不是本文的重点,有兴趣可以单独了解一下。
所以,在 Api23 以下,executeAction()
是会被循环调用,基本上其内的 mActions 只要有未执行的 Runnable 立刻就会被消费掉。
所以在 Api23 以下的设备上,View.post() 基本上是靠谱的,post 出去的 Runnable 都会有机会执行到。
2.3 Api24 的细节
再来看看在 Api24 中的实现细节,在 Api24 中,调用的是 getRunQueue().post()
方法,它操作的是一个 HandlerActionQueue
对象。
内部的结构其实和 Api23 很像,也是维护了一个 HandlerAction 的数组 mActions 。
最终消费掉 mActions 的地方,依然是一个 executeActions()
方法。
回到根本的问题,executeActions()
方法在什么时机会被调用到,继续追查可以看到它在 View.dispatchAttachedToWindow()
方法中,会被调用。
既然,executeActions()
方法,在 Api24 及以上,只会在 dispatchAttachedToWindow()
的方法中,才有机会被调用到,而 View.dispatchAttachedToWindow()
方法,只有在这个 View 通过 addView()
等方法,加入到一个 ViewGroup 的时候,才会被调用到。这就导致写在 Layout 布局中的控件,是不会有机会再调用 addView()
方法的,所以它永远也得不到执行。这也就到时了 Api24 下,View.post()
表现的现象不一致的缘故。
感谢各位的阅读!关于“使用View.post()需要注意什么”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!
另外有需要云服务器可以了解下创新互联scvps.cn,海内外云服务器15元起步,三天无理由+7*72小时售后在线,公司持有idc许可证,提供“云服务器、裸金属服务器、高防服务器、香港服务器、美国服务器、虚拟主机、免备案服务器”等云主机租用服务以及企业上云的综合解决方案,具有“安全稳定、简单易用、服务可用性高、性价比高”等特点与优势,专为企业上云打造定制,能够满足用户丰富、多元化的应用场景需求。
本文标题:使用View.post()需要注意什么-创新互联
文章地址:http://azwzsj.com/article/dhsppc.html