TextView.setText(...)在按钮侦听器内的循环中不起作用

时间:2018-06-11 18:35:06

标签: java android multithreading

我们说我有一个按钮和一个标签。我想在一个按钮监听器的循环中更新标签100000次。问题是我们没有看到更新文本的过程,只看到了最后一个设置值。

@Override
protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    generateLabel = findViewById(R.id.label);
    generateButton = findViewById(R.id.button);

    generateButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            for (int i = 0; i < 100000; i++) {
                generateLabel.setText("" + i);
            }
        }
    });
}

看起来我们必须在更新标签之前从onClick(...)方法中退出。所以,我试过了:

  • 运行我自己的主题,
  • 调用runOnUiThread(...),
  • 执行AsyncTask子类,

但每次我得到一个例外,说我不应该修改来自原始线程的视图层次结构的View。即使刷新标签并使其volatile也没有帮助。有什么想法吗?

2 个答案:

答案 0 :(得分:0)

public static int counter = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    findViewById(R.id.button).setOnClickListener(
            new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    counter = 0;
                    new Runner().run();
                }
            }
    );
}

public class Runner implements Runnable {
    @Override
    public void run() {
        if(counter++ < 1000) {
            ((TextView) findViewById(R.id.label)).setText("Counter: " + counter);
            new Handler().postDelayed(new Runner(), 100);
        }
    }
}

答案 1 :(得分:0)

这不会有多种原因,首先是你试图在&lt; ~1秒内更新你的用户界限100,000次。注意当你打电话setText()时,你实际上是在告诉系统渲染文本你已经过去了在&lt; ~1秒内渲染和重新渲染100k次将导致您的应用崩溃。现在,如果您要说我将在某些后台线程中运行此操作,这也是不可能的,因为您只能在UI线程上执行UI工作,或者主线程和BG线程不能用于此目的。唯一的方法是在AsyncTask中使用onProgressUpdate(),但这通常用于不同的目的,并且该方法的UI更新也发生在主线程上,所以它基本上做了你现在正在做的事情肯定会导致崩溃。