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

网络编程 2025-03-29 06:39www.168986.cn编程入门

一、前言

在Android开发中,View.post()方法常被用于将任务投递到主线程执行,其背后通过Handler进行实现,为我们省去了创建Handler对象的繁琐过程。从Android 7.0(API level 24)开始,这一方法似乎变得不那么可靠了。你可能会发现通过post()方法投递的Runnable任务可能永远不会被执行。

二、View.post()在Android 7.0的变化

1. 方法差异:从源码层面分析,Android 7.0对View.post()方法的改动主要体现在当View的mAttachInfo为null时,执行的逻辑发生变化。相较于API level 23及以下版本,API level 24中的实现会通过getRunQueue().post(action)的方式处理,而API level 23及以下则会通过ViewRootImpl.getRunQueue().post(action)。

2. API 23及以下版本的细节:

- ViewRootImpl是Activity的ViewTree的根节点的实例,负责管理DecorView和ViewTree。每个ViewRootImpl实例都承载着一个用于处理Runnable任务的队列sRunQueues,这是一个静态变量,意味着在App的生命周期内,这个消息队列是共享的。

- 在API 23及以下版本中,通过ViewRootImpl的getRunQueue().post()方法添加任务时,会将这些任务包装成HandlerAction对象并放入mActions这个ArrayList中。这些任务何时被消费掉呢?它们会在executeActions()方法中被处理。

- executeActions()方法是在TraversalRunnable的doTraversa()方法中调用的。TraversalRunnable则通过Choreographer的postCallBack()方法进行循环调用。Choreographer通过发送MSG_DO_SCHEDULE_CALLBACK类型的消息进行循环调用,间隔与VSync同步。这意味着在API 23以下的设备上,executeAction()方法会被循环调用,只要存在未执行的Runnable任务,它们会立即被执行。在这些设备上,View.post()方法是可靠的。

介绍Api24细节:关于View.post()的隐秘差异

当我们深入Api24的细节时,有一个特别引人注目的点值得我们关注——那就是View.post()方法的实现。在这个版本中,该方法通过操作一个HandlerActionQueue对象来实现其功能。

其内部结构与Api23颇为相似,维护着一个名为mActions的HandlerAction数组。关键的消费动作由executeActions()方法完成。这个方法究竟在何时被触发呢?追查下去,你会发现它在View的dispatchAttachedToWindow()方法中被调用。

问题的关键在于,在Api24及其以上版本中,executeActions()方法的触发仅限于dispatchAttachedToWindow()方法。而这个方法只有在View通过addView()等方法加入到ViewGroup中时才会被调用。这意味着,在Layout布局中的控件不会触发addView()方法,因此它们永远无法执行executeActions()方法。这就是导致Api24下View.post()表现不一致的原因。

小结:

View.post()方法在不同版本的Android系统中表现不同,其根本原因在于Api23和Api24中executeActions()方法的调用时机存在差异。当View还没有mAttachInfo对象时,其表现尤为明显。

在使用View.post()方法时,我们需要谨慎选择使用场景,确保在View已经显示后再调用此方法(此时mAttachInfo已经不为空)。为了避免潜在的问题,我们可以选择使用Handler.post()方法来替代。

以上所述是长沙网络推广团队为大家揭示的View.post()的使用陷阱,希望能对大家有所帮助。如有任何疑问,请随时留言,长沙网络推广团队会及时回复。感谢大家对狼蚁SEO网站的支持与关注!

这段文本保持了原文的风格和特点,同时进行了语言的优化和细节的丰富,使其更加生动、吸引人。

上一篇:vue 插件的方法代码详解 下一篇:没有了

Copyright © 2016-2025 www.168986.cn 狼蚁网络 版权所有 Power by