Android Handler.post,究竟发生了什么

时间:2014-04-10 09:18:40

标签: android handler runnable

几天以来,我试图找出如果我在

中执行代码会发生什么
void function(){

  //somePreExecutionCode
  new Handler().post(new Runnable(){
    @Override 
    public void run(){
       //someCode
    }
  });
}

似乎它没有阻止UI,因此调用function()的按钮在someCode完成之前不会卡在点击的位置。 但是如果somePreExecutionCode启动了progressBar,那么当someCode完成时,progressBar会在完全相同的时刻显示。 我知道,有AsyncTasks,但还有其他可能吗?

之间的区别是什么?
new Handler().post 

View.post

3 个答案:

答案 0 :(得分:8)

创建Android应用程序时,系统会创建一个主要的执行线程。此线程称为UI线程,所有与UI相关的操作都发生在此线程上,以避免同步问题。

在此线程上创建Looper实例,该实例具有MessageQueue数据结构。 Looper将处于无限循环中,等待阅读Message上发布的Runnable / MessageQueue个实例。要将Message7 / Runnable添加到MessageQueue,请使用Handler

当您创建Handler实例时,它将与当前执行线程以及在该特定线程上创建的Looper实例相关联。

因此,当您通过处理程序发布消息时,消息将添加到MessageQueue中,该消息将由Looper以FIFO顺序读取,并将传递给目标。

new Handler()。post()和View.post有点不同。

  • 当您通过View.post发布消息时,可以保证消息将发布在UI线程的MessageQueue上,因为它在内部使用在UI线程上创建的Handler实例。
  • 如果您在UI线程上创建Handler实例并在任何线程上使用它发布消息,则消息将发布到UI线程的MessageQueue。
  • 如果您在非UI线程上创建Handler实例并使用它发布消息,它们将发布在非UI线程的MessageQueue上。

答案 1 :(得分:4)

简单地说,有 Looper线程,例如 UI线程。这样的线程有自己的Looper,它为线程运行一个消息循环。

此类线程通常有一个Handler,用于处理其Looper的消息 - 覆盖public void handleMessage(Message msg)或执行Runnable,该消息已发布到其looper的消息中队列中。

当您在 UI线程的上下文中创建Handler时(就像您在代码中所做的那样),它会与 UI线程的 looper相关联,因此您的\\someCode UI线程上运行。

我想,在您的用例中new Handler().post(Runnable)View:post(Runnable)大致相同,因为它们都会在 UI线程消息队列中添加Runnable

但他们不一样。

  • View:post(Runnable)会将Runnable添加到 UI线程 looper的消息队列中;
  • Handler:post(Runnable)会将Runnable添加到其关联的线程循环播放器消息队列

我的解释非常直观,如果我错了,请纠正我。

答案 2 :(得分:0)

根据the Android View's documentation

  

Runnable将在用户界面线程上运行

根据the Android Handler's documentation

  

Runnable将在此处理程序所附加的线程上运行

所以,在Handler的情况下,你可以在你想要的任何线程中创建它,它是一种锚,它将执行你在创建它的线程中提供的Runnable。

在View.post中,您将始终在uI线程中执行Runnable。