简述View#post与Handler#post的区别 ?
参考回答:
View#post()和Handler#post()都可以用来将任务添加到消息队列中,但它们的作用和使用场景有所不同。View#post()是将任务发布到当前View所在的UI线程的消息队列中,并且通常用来更新UI,而Handler#post()是将任务发布到指定的Handler对应的Looper的消息队列中,可以指定任务执行的线程。
详细讲解与拓展:
1. View#post()
- 功能:将一个
Runnable任务添加到当前View所在的UI线程的消息队列中,并等待系统在合适的时机执行该任务。 - 使用场景:
View#post()通常用于需要在UI线程执行的任务,尤其是更新UI时。它可以确保任务在当前View的所属线程中运行,通常是主线程。示例:
myView.post(new Runnable() { @Override public void run() { // 在UI线程中执行更新UI的操作 myView.setVisibility(View.VISIBLE); } }); - 执行时机:
post()方法将任务加入到当前View的UI线程的消息队列中,任务会在下一帧绘制前执行。也就是说,任务会在当前事件循环结束之后执行。
2. Handler#post()
- 功能:
Handler#post()将一个Runnable任务添加到与Handler关联的Looper的消息队列中。Handler会根据其所绑定的Looper来决定任务在哪个线程执行。 -
使用场景:
Handler#post()可以用于任何线程,只要该Handler与指定的Looper(主线程或子线程)关联。它通常用来在非UI线程中发送消息或任务,确保任务在指定的线程中执行。示例:
Handler handler = new Handler(Looper.getMainLooper()); handler.post(new Runnable() { @Override public void run() { // 在UI线程中执行更新UI的操作 myView.setVisibility(View.VISIBLE); } });这个示例中,
Handler与主线程的Looper关联,因此任务会在主线程中执行。 -
执行时机:
Handler#post()将任务添加到与Handler绑定的Looper的消息队列中,任务将在该Looper的事件循环中被处理。对于主线程的Handler,任务会在主线程执行。
3. 区别总结:
-
目标线程:
View#post()始终将任务发送到UI线程,即当前View所在的线程。Handler#post()将任务发送到与该Handler关联的Looper对应的线程,通常是主线程,但也可以是任何Handler所绑定的线程。
- 灵活性:
View#post()不需要指定线程,因为它默认将任务发送到UI线程。Handler#post()更为灵活,可以选择目标线程,通过指定Looper来控制任务执行在哪个线程。
- 常见用途:
View#post()适用于在UI线程中执行与View相关的更新操作。Handler#post()适用于任何线程间的任务调度,特别是在子线程中更新UI或进行异步操作时。
总结:
View#post()和Handler#post()都可以将任务添加到消息队列中,但它们的主要区别在于目标线程的不同。View#post()将任务发送到UI线程,通常用于更新UI;而Handler#post()允许更灵活的选择目标线程,它会将任务发送到与Handler关联的Looper的消息队列中。