简述View#post与Handler#post的区别 ?
在Android开发中,View#post(Runnable)
和Handler#post(Runnable)
都是用于将一个Runnable
任务提交到主线程的消息队列中去执行。这两种方法都被广泛用于在非UI线程中更新UI组件或执行UI操作,但它们在使用上有一些关键的区别。
View#post(Runnable)
- 定义:
View#post(Runnable)
是View
类的一个方法,它允许你将一个Runnable
对象排队到与该View
相关联的消息队列中去执行。 - 使用场景:当你需要在一个特定的
View
上执行某些操作,并且这个操作需要依赖于View
的属性或状态时(比如,需要在视图完全绘制后才执行),使用View#post
是很合适的。 - 特点:
- 任务的执行时机依赖于
View
所在的窗口的消息队列,如果View
还没有被添加到窗口(即getWindowToken() == null
),提交的任务将不会被执行。 View#post
是依附于View
的生命周期的,如果View
被销毁或移除,那么这些任务可能永远不会执行。
- 任务的执行时机依赖于
Handler#post(Runnable)
- 定义:
Handler#post(Runnable)
是Handler
类的一个方法,用于将任务发送到与Handler
关联的消息队列中执行。 - 使用场景:适用于不依赖于任何特定
View
状态或属性的任务执行,特别是当你需要更新UI,但更新操作与任何特定View
无关时。 - 特点:
- 可以指定
Handler
关联的线程(通过在创建Handler
时指定的Looper
),因此任务可以在任何指定的线程执行,虽然通常Handler#post
是用于主线程的。 - 任务总是会被执行,除非
Looper
正在退出,这使得Handler#post
在很多情况下更加灵活和可靠。
- 可以指定
选择依据
- 如果你需要确保任务在特定
View
上下文中执行,比如在View
布局完成后立即执行某些动画,或者任务依赖于View
的某些属性,那么使用View#post
更合适。 - 如果你的任务只是简单地更新UI或执行一些不依赖于特定
View
的操作,使用Handler#post
会更好。这种方式不仅代码更清晰,而且减少了因View
生命周期结束而导致的执行不确定性。
总的来说,虽然View#post
和Handler#post
在功能上相似,都是将代码块推迟到未来某个时间点执行,但选择哪一种应根据任务的具体需求和上下文环境来定。