Android为什么要在处理程序或异步任务中更新用户界面

Android为什么要在处理程序或异步任务中更新用户界面,android,android-asynctask,handler,message-queue,Android,Android Asynctask,Handler,Message Queue,如果您已经在ui线程上,为什么要更新处理程序、asynctask或runOnUiThread中的ui元素,对此我感到困惑 考虑下面的代码段,编号从1到4:(出于演示目的,可能有语法错误) 正如您从示例1到4中所看到的,我不明白您为什么需要使用2、3或4,因为1您已经在UI线程上了 换句话说,我是说#1-#4是一样的——也就是说,你想在UI线程/主线程上执行一些东西,那么告诉我,如果#1已经在UI线程上,为什么要使用#2、#3或#4 它们之间有什么区别 请提供任何文档或实际用例的引用 谢谢 如果您

如果您已经在ui线程上,为什么要更新处理程序、asynctask或runOnUiThread中的ui元素,对此我感到困惑 考虑下面的代码段,编号从1到4:(出于演示目的,可能有语法错误)

正如您从示例1到4中所看到的,我不明白您为什么需要使用2、3或4,因为1您已经在UI线程上了

换句话说,我是说#1-#4是一样的——也就是说,你想在UI线程/主线程上执行一些东西,那么告诉我,如果#1已经在UI线程上,为什么要使用#2、#3或#4

它们之间有什么区别

请提供任何文档或实际用例的引用


谢谢

如果您已经在UI线程上,则无需使用
runOnUiThread
或您描述的任何其他情况。这些是为您不在UI线程中的情况提供的

阅读《开发者指南》。它包括一些示例,解释了如果您试图在UI线程之外的UI上执行操作,会出现什么问题,并解释了避免这些操作的各种选项


但是在你的例子中,简单地说,你在一个活动中,你没有产生任何其他线程,因此你在UI线程中,不需要任何特殊的方法来访问UI。

我发现有点难以说出你的问题到底是什么,但是关于你的论文有一些注释

不,1到4不一样

  • 有效性:是的,如果您已经在UI线程上,并且没有昂贵的计算或冗长的I/O操作要做,那么就不需要从#2到#4中进行选择
  • 时机:根据具体情况,#2到#4的效果有一定的概率比#1晚一点出现
  • 复杂性/等待:通常只有#4可以让您干净地等待阻塞I/O或进行冗长的计算。#2也可以工作,这取决于
    处理程序
    ,但这不是处理程序的用途
  • 处理程序:在#2中,根本不能保证您使用的是main/UI线程处理程序。代码可以在非main/UI线程上运行
  • 3是一种方便的方法。
所以不,它们在总体上是完全不同的

p.S.

  • 优先级:取决于使用
    处理程序时代码的线程类型,以及在
    异步任务的
    doInBackground()
    的任何默认情况下,您的代码将以后台优先级运行,并且必须与系统上的所有其他后台线程一起使用10%的CPU时间,除非您调整优先级。一段时间
p.p.S.

既然你在评论中问了“另一个问题”:

  • 如果您确信自己在UI线程上并且不进行计算和/或I/O,那么1是最有效和最直接的
  • 2仅在处理程序使用main/UI线程时有效。为什么要用它?如果您在代码中的某个地方,与任何可用的
    上下文
    视图
    分离,您仍然可以执行
    newHandler(Looper.getMainLooper())
    ,这将为UI线程提供一个
    处理程序
  • 3指
    查看
    上下文
    相关便利方法。只要手头有一个对象,就可以使用它们在UI线程上执行某些操作。
  • 如果您正在进行昂贵的操作或等待,则必须使用4。然而,
    AsyncTask
    只是一个方便的类,用于相对较短的操作。

1这是在UI线程中更新UI的正确且最直接的方法

  • 如果您只想简单地更新UI,则不需要2和4
当我们需要在单独的线程中执行任务时,特别使用2

3()从未在oncreate()中使用,因为您已经在UI线程上。它用于从非UI线程更新UI,例如从异步任务的doinbackground()更新UI


4不应仅用于更新UI元素,其主要目的是仅在活动的后台执行任务。虽然执行前和执行后功能可以更新UI。

当然感谢您的回答,但在很多情况下,我在网上看到的很多示例中,它们也没有新线程,但它们使用这些#2-#4进行更新,我不知道为什么。因此,我对你的答案表示怀疑,但我可能是错的。鉴于上述示例,我们只是更改textview的文本字段,为什么稍后会出现#2到#4?@XyzNullPointer文本设置与其他UI属性更改一样,不会立即生效。对于UI来说,立即呈现所有内容的效率太低(而且,它最终会闪烁)。因此,在UI线程上,有一个UI实体触发重新渲染。在#1中,你立即给它做某事的理由。在第二到第三节中,你首先安排一些事情,让它有理由做一些事情。当然,在您的小例子中,您不会注意到有多大的不同。@XyzNullPointer看到了您的一条评论并更新了我的答案。嗨,Class Stacker,非常感谢您。你能解释一下我添加的案例5吗?@XyzNullPointer#5我已经解释过了;这些是我在第3页的P.P.s.中提到的
View
s的便利功能。通常,您手头有
视图
对象,它们是在
上下文中创建的
,所以它们很容易为您的方便提供这些方法。您对#3的回答对我来说毫无意义,我的意思是rununuithread是一种活动方法,如何从另一个线程调用它…?另一个线程表示非UI线程,例如异步任务的doinbackground()
// in MainActivity.java #1
public void onCreate(Bundle bundle) {
     setContentView(R.layout.main);
     TextView name = (TextView)findViewById(R.id.name);
     name.setText("Name Changed!!");
}


// in MainActivity.java #2
public void onCreate(Bundle bundle) {
     setContentView(R.layout.main);
     TextView name = (TextView)findViewById(R.id.name);
     handler.post(new Runnable() {
           public void run() {
               name.setText("Name Changed!!");
           }
          });
}

// in MainActivity.java #3
public void onCreate(Bundle bundle) {
     setContentView(R.layout.main);
     TextView name = (TextView)findViewById(R.id.name);
     runOnUiThread(new Runnable() {
           public void run() {
               name.setText("Name Changed!!");
           }
          });
}

// in MainActivity.java #4
public void onCreate(Bundle bundle) {
     setContentView(R.layout.main);
     ...same thing,...update textview in AsyncTask
}

 // in MainActivity.java #5
public void onCreate(Bundle bundle) {
     setContentView(R.layout.main);
      TextView name = (TextView)findViewById(R.id.name);
     name.post(new Runnable() {
           public void run() {
               name.setText("Name Changed!!");
           }
          });
}