TimerTask.run() 中的命令执行顺序错误(在 Android 中编写的应用程序 Java)

Wrong order of commands execution in TimerTask.run() (in Android app written in Java)

我正在编写一个简单的 android 应用程序(在 Java 中),它应该能够加载 *.txt 文件并每 0.5 秒一次显示一个单词的内容。我设法将一个文本文件的内容放入一个字符串数组中,该数组在每个索引下存储一个单词。我正在使用 Timer 和 TimerTask 以给定的时间间隔在 TextView 中显示数组中的单词。为了实现这个目标,我的 TimerTask 运行() 方法首先调用 TextViev.setText() 方法,该方法在当前索引处显示数组中的项目,然后递增索引(或者我认为如此)。事实证明,索引首先递增,然后 TextViev.setText() 方法被调用(尽管 TimerTask 的重写 运行() 方法中的命令顺序)。我的问题是:为什么命令按这个顺序执行,我该如何解决?

TimerTask readingTimerTask = new TimerTask() {
            @Override
            public void run() {
                if (wordIndex < textArr.length - 1) {
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            tvWords.setText(textArr[wordIndex]);
                            Log.i(LOG_TAG, "setText() called. wordIndex: " + String.valueOf(wordIndex));
                        }
                    });
                    wordIndex++;
                    Log.i(LOG_TAG, "wordIndex incremented. New value of wordIndex: " + String.valueOf(wordIndex));
                } else {
                    stopReading();
                }
            }
        };
mTimer = new Timer();
Log.i(LOG_TAG, "Timer is starting. wordIndex: " + String.valueOf(wordIndex));
mTimer.schedule(readingTimerTask, 100, displayTimeInMs);

Logcat 看起来像这样:

D/MainActivity: wordIndex in onActivityResult (file loaded): 0
I/MainActivity: Timer is starting. wordIndex: 0
I/MainActivity: wordIndex incremented. New value of wordIndex: 1
I/MainActivity: setText() called. wordIndex: 1
I/MainActivity: wordIndex incremented. New value of wordIndex: 2
I/MainActivity: setText() called. wordIndex: 2
I/MainActivity: wordIndex incremented. New value of wordIndex: 3
I/MainActivity: setText() called. wordIndex: 3
I/MainActivity: wordIndex incremented. New value of wordIndex: 4
I/MainActivity: setText() called. wordIndex: 4
I/MainActivity: wordIndex incremented. New value of wordIndex: 5
I/MainActivity: setText() called. wordIndex: 5
I/MainActivity: Timer has been stopped. wordIndex: 5

为什么命令按这个顺序执行?

从后台线程调用时,runOnUiThread() 不会等待 run() 中的命令完成后再返回。它安排它们在 单独的线程 上执行:UI 线程。

我假设您的代码片段是在 UI(或“主”)线程上调用的。同时,您的 TimerTask 引入了第二个线程:它的内部后台工作者。 IOW,你已经创建了一个 race condition.

wordIndex++保证首先执行,在这种情况下,但它通常会“赢得”比赛,因为它需要一点时间UI 线程处理 Runnable.

我该如何解决?

您可能不打算在您的程序中引入多线程——这会使事情变得相当复杂,而且不适合新手程序员。您可能想要使用 CountDownTimer,而不是 TimerTask。这将帮助您将所有内容都放在 UI 线程上。