Android 处理程序仅使用最后一个 setText() 更新 TextView

Android Handler updates TextView only with last setText()

以下代码来自 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.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 
                }
    
            });
        }
    

handler.postDelayed(this,1000);

这用于在 1 秒后 运行 您的函数。这是1秒的延迟。

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

Why does it skip hander.post() in the first place?

不是跳过,会在onResume()returns之后执行。所有 Runnables,通过与主线程关联的处理程序排队,仅在 onResume() returns.

之后开始执行

Why doesn't the first one work?

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

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

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

Why doesn't the first one work? I am expecting the text to jump back and forth from "hello" to "hh:mm:ss".

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

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

why is this used in postDelay(this, 100). shouldn't it be this.run()?

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