Android:Activity.runOnUiThread和View.post有什么区别?

104

Activity.runOnUiThreadView.post 有何区别?能否解释一下?


4个回答

109

两者实际上没有真正的区别,唯一不同的是当你无法直接访问活动时,View.post 会很有用。

在两种情况下,如果不在 UI 线程上,则会在后台调用Handler#post(Runnable)

正如 CommonsWare 在评论中提到的那样,两者之间存在差异 - 当在 Ui 线程上调用时,Activity#runOnUiThread 将直接调用 run 方法,而 View#post 将在队列上发布 runnable(例如调用 Handler#post

我的重点在于,两者的目标相同,对于使用它的人来说,没有区别(并且实现将来可能会发生变化)。


76
一个区别:runOnUiThread() 会检查当前线程,如果我们在主应用程序线程上运行,则立即执行 Runnable。而 post() 则无论在哪个线程调用,始终会把 Runnable 放到队列中。 - CommonsWare
1
谢谢,现在我能够根据您的解释和@CommonsWare的评论看出区别了。 - Alexander Kulyakhtin
4
@Ashwin:“你说runOnUiThread()会立即执行Runnable”,不,我没有。请重新阅读评论。我说:“如果我们正在主应用程序线程上运行,'runOnUiThread()将检查当前线程并立即执行Runnable”(强调添加)。 “这是否意味着目前在UI线程上的任何内容都被忽略,而这个方法被优先考虑?”--“目前在UI线程上的任何内容”就是runOnUiThread()方法的调用。 - CommonsWare
1
@barn.gumbl:在这种情况下,我查看了源代码。 - CommonsWare
2
有一个区别。向未附加到窗口的视图发布内容将不起作用。虽然这不是一个巨大的区别,但这可能会导致微妙的错误,并且如果您不知道存在差异,则很难导航。 - dcow
显示剩余7条评论

23

Activity.runOnUiThread和view.post()之间的另一个区别是,view.post()中的runnable在视图附加到窗口后调用。


你的意思是如何展示?变得可见吗?在不可见的视图上根本没有被调用吗? - Alexander Kulyakhtin
纠正了模棱两可的问题,Alex。 - pareshgoel
5
在我看来,这是最重要的区别。许多人使用view.post()来执行那些需要在视图附加后执行的任务。 - Sotti
3
这是不正确的。这从未是事实,但曾经在View.java的JavaDoc中错误地声明了“仅当View附加到窗口时,View.post才能在另一个线程中工作”。这在2012年10月15日被修复,但需要一段时间才能为Android开发人员所理解。 - Alex Cohn
@pareshgoel 这个差异的来源是什么? - apostleofzion

17

对于大多数情况来说,两者都可以接受,并且在很大程度上它们是可以互换的,但它们仍然存在细微的差别。当然最大的区别是其中一个可从 Activity 获取,而另一个则可从 View 获取。这两者之间有很多重叠,但有时在 Activity 中你将无法访问到 View,而有时在 View 中你将无法访问到 Activity

我曾经遇到过一个边缘情况,就是针对 View.post,我在另一个关于View.post的SO问题回答中提到:只有当 View 附加到窗口时,View.post 才能在 另一个线程 中正常工作。这通常不会成为问题,但有时可能会导致 Runnable 永远不会被执行,特别是如果你在 ActivityonCreate 方法中调用了 View.post。一个替代方案是使用 Handler.post,这正是 Activity.runOnUiThreadView.post 内部使用的。

(因准确性而编辑,添加了“从另一个线程”)


1
onCreate() 中,它也可能会失败吗?嗯,我期望它在这种情况下会发布到由 ViewRoot 提供的 Handler - Jens
5
@Jens 是的,我浏览了源代码,如果Runnable尚未附加,则View.post应将其添加到队列中以稍后执行。 我没有深入研究源代码,但文档确实说:“当此视图附加到窗口时,仅当在UI线程外部调用此方法。” 因此,我认为如果在当前线程上,那么您所说的是正确的,如果不是,它可能会忽略Runnable。 我的代码中肯定发生过这种情况。 - kabuko
@kabuko 谢谢你的回答,它从另一个角度解释了这个问题。我不能接受超过1个答案,看不出背后的逻辑,应该在元论坛中讨论。 - Alexander Kulyakhtin
3
这是不正确的。这从来就不是真的,但在某个时候,View.java的JavaDoc错误地陈述了"只有当View连接到窗口时,View.post才能在另一个线程中工作"。这在2012年10月15日被修复,但需要一段时间才能为Android开发人员所理解。 - Alex Cohn

0
另一个区别是:post 是每个视图;runOnUiThread 是每个活动。
这意味着将来可能会做到 view.getQueue / activity.getQueue,并且可以精确地获取您想要的内容,而无需自己编写跟踪或过滤代码。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接