【问题标题】:Android Handler updates TextView only with last setText()Android Handler 仅使用最后一个 setText() 更新 TextView
【发布时间】:2019-06-29 13:35:07
【问题描述】:

以下代码来自 Head First Android。这是一个秒表应用程序。

我对以下代码有几个问题:

  1. 代码运行如下 -> OnCreate -> runTimer() (跳过 handler.post()) -> OnStart -> onResume -> 回到 handler.post()。

为什么它首先跳过hander.post()

  1. 我有两个 textView.setText()。但是第一个不起作用。它总是最后一个。我放第二个只是为了看看代码在 postDelay() 方法之后做了什么。

为什么第一个不起作用?我期待文本从“hello”来回跳转到“hh:mm:ss”。

  1. 那么在 postdelay() 执行后的 1 秒延迟期间究竟发生了什么。

代码是否开始正常运行,并在 1 秒时调用 postDelay()?

  1. 为什么在 postDealy(this, 100) 中使用 this。不应该是this.run()吗?

    public class MainActivity extends AppCompatActivity {       
        private boolean running = false;
        private int counter = 0;
        private Handler handler = new Handler();
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            runTimer();
        }
    
        public void onClickStart(View view){
            running = true;
        }
    
        public void runTimer(){
            final TextView textView = findViewById(R.id.timer);
    
            handler.post(new Runnable() {
    
                @Override
                public void run() {
                    int hours = counter/3600;
                    int minutes = (counter%3600)/60;
                    int secs = counter%60;
    
                    String time = String.format("%d:%02d:%02d", hours, minutes, secs);
                    textView.setText(time); // Doesn't set it to this - see last line 
    
                    if(running){
                        counter++;
                    }
                    handler.postDelayed(this,1000); // what does happens between next one second 
                    textView.setText("hell0"); // Always set it to this 
                }
    
            });
        }
    

【问题讨论】:

    标签: android android-activity textview android-handler


    【解决方案1】:

    为什么它首先跳过hander.post()

    不跳过,在onResume()返回后执行。所有Runnables,通过与主线程关联的处理程序排队,只有在onResume()返回后才开始执行。

    为什么第一个不起作用?

    确实有效。您只是无法直观地看到它,因为 textView.setText() 这两个方法调用“几乎”同时被调用。

    在每个run() 发生以下调用序列:

    • textView.setText(time),
    • 相同的Runnablehandler.postDelayed(this,1000) 一起发布到队列中。紧接着
    • textView.setText("hell0") 被调用

    为什么第一个不起作用?我期待文本从“hello”来回跳转到“hh:mm:ss”。

    您应该实现一个额外的逻辑,以便在每次执行 run() 时在 time"hell0" 之间切换。

    例如在 Activity 中创建一个布尔标志,并根据标志值设置时间或“hell0”(不要忘记在每次执行run() 时更改标志值)

    为什么在 postDelay(this, 100) 中使用 this。不应该是this.run()吗?

    不,this.run() 是同步(并立即)执行的,并且是 void 类型。代码不会编译,因为 postDelay() 需要 Runnable 类型,而不是 void

    【讨论】:

    • 您是对的,在textView.setText(time) 之后将值设置为HH:MM:SS。但它没有在 GUI 中更新。我通过添加断点进行检查。执行textView.setText(time)后,即使texview的值设置为HH:MM:SS,GUI仍然显示Helloo
    • @lynxx,当设置断点“执行textView.setText(time)”时,您不会在 UI 上看到HH:MM:SS,因为主线程已停止,TextView 无法更新其布局。只需在Activity 中创建一个标志布尔值并根据标志值设置time"hell0"(不要忘记更改每个run() 的标志值)。在那之后,你就明白了。
    【解决方案2】:

    handler.postDelayed(this,1000);

    这曾经在 1 秒后运行您的函数。这是 1 秒的延迟。

    handler 中编写的代码将在一秒钟后执行。就这样。

    【讨论】:

      猜你喜欢
      • 2012-07-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-30
      • 2012-03-09
      相关资源
      最近更新 更多