Java 能够在doInBackground中更新UI

Java 能够在doInBackground中更新UI,java,android,android-asynctask,Java,Android,Android Asynctask,据我所知,我们无法从AsyncTask的doInBackground方法中更改UI元素,但在执行相同操作和更改TextView的文本时,它不会给出任何异常 public class MainActivity extends Activity { TextView tv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);

据我所知,我们无法从AsyncTask的doInBackground方法中更改UI元素,但在执行相同操作和更改TextView的文本时,它不会给出任何异常

 public class MainActivity extends Activity {

  TextView tv;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    tv = (TextView)findViewById(R.id.tv);
    Toast.makeText(MainActivity.this, "Main : " + Thread.currentThread().getName(), Toast.LENGTH_SHORT).show();
    new DemoAsync().execute();
  }

  class DemoAsync extends AsyncTask<Void, Void, String> {

    @Override
    protected String doInBackground(Void... params) {
        String threadName = "Async : " + Thread.currentThread().getName();
         for(int i=0;i<1000;i++) {
            tv.setText("Changed " + i);
        }
        return threadName;
    }

    @Override
    protected void onPostExecute(String threadName) {
        Toast.makeText(MainActivity.this, threadName, Toast.LENGTH_SHORT).show();
    }
   }
 }
公共类MainActivity扩展活动{
文本视图电视;
@凌驾
创建时受保护的void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv=(TextView)findviewbyd(R.id.tv);
Toast.makeText(MainActivity.this,“Main:+Thread.currentThread().getName(),Toast.LENGTH_SHORT.show();
新建DemoAsync().execute();
}
类DemoAsync扩展了AsyncTask{
@凌驾
受保护字符串doInBackground(无效…参数){
String threadName=“Async:+Thread.currentThread().getName();

对于(int i=0;i,您不应从
doInBackground
访问UI,如中所述:

不要从UI线程外部访问Android UI工具包

在这里结账

AsyncTask允许正确且轻松地使用UI线程。此类允许在UI线程上执行后台操作和发布结果,而无需操作线程和/或处理程序


编辑:在OOP中,您可以从内部类访问全局变量。因此,从这个角度来看,在本例中,类扩展AsyncTask是内部类,您可以访问TextView tv;因为在主UI线程中调用execute,所以您可以修改,但如果它不是内部类,则无法访问根据abstrac定义的变量这是因为doInBackground在另一个线程(不是UI)中运行。简言之,您无法在doInBackground()中修改UI元素,但内部类可以访问全局声明的小部件对象,以更改容器中的值,正如在这个问题中所做的那样。这只是一个计时误解:乍一看似乎是
tv.setText(“更改的”+i);
在doInBackground()中更改UI中的视图

但是

实际上,当执行最后一个setText时,UI还没有准备好并与活动连接,因此循环中的最后一个setText会更改尚未在UI中的视图


如果我们延迟循环,例如10000次迭代,UI将启动,我们将得到异常“只有创建层次结构视图的原始线程才能接触其视图”。

我们可以从doinbackground更新UI使用下面的函数来更新UI

runOnUiThread(new Runnable() {
                public void run() {
                   Write your code here to run in UI thread
                }
            });

来源?请引用?来源已添加到我的answer@barq-但如果我这样做会发生什么?它是否会崩溃?为什么它只会在Toast而不是TextView的情况下崩溃?来源没有说明您可以在doInBackground()中更新UI。如果您在该页面上搜索-只有6个实例
doInBackground()
被引用,并且没有说明您可以在此处更新UI。这很奇怪,但tv变量甚至不是final。如何从内部类访问它。如果确实发生了这种情况,这确实非常奇怪!当应用程序崩溃时,您的日志输出是什么?tv是一个实例变量,因此此处不需要final!Thread.currentThread().getName();在AsyncTask中,您真正想做什么?这不是答案,请对此进行否决表决。让我更具体地说,您可以在UI线程中修改UI元素,而不是在后台线程中修改UI元素。是的,您是对的,您不能在DoinBacGround()中修改UI元素因为它在后台运行。这里您声明了TextView tv;全局,并且由于内部类可以访问全局对象,所以可以修改内容。您还调用了execute()在UI线程上,完全理解这一点是可能的,请查看官方文档。请引用带有链接的源代码。这是OOP(内部类,全局变量)中关于AsyncTask的基本概念,已经提供了文档链接。是否可以在
doInBackground()
中更新UI?如果可以,请引用源代码?