35

我想在 Android 中制作一个简单的计时器,每秒更新一个 TextView。它只是像扫雷一样计算秒数。

问题是当我忽略 tvTime.setText(...) 时(使其 //tvTime.setText(...),在 LogCat 中将每秒打印以下数字。但是当我想将此数字设置为TextView(在另一个线程中创建),程序崩溃。

有谁知道如何轻松解决这个问题?

这是代码(在启动时调用方法):

private void startTimerThread() {
    Thread th = new Thread(new Runnable() {
        private long startTime = System.currentTimeMillis();
        public void run() {
            while (gameState == GameState.Playing) {
                System.out.println((System.currentTimeMillis() - this.startTime) / 1000);
                tvTime.setText("" + ((System.currentTimeMillis() - this.startTime) / 1000));
                try {
                    Thread.sleep(1000);
                }
                catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    });
    th.start();
}

编辑:

终于我明白了。这是解决方案,对于那些感兴趣的人。

private void startTimerThread() {       
    Thread th = new Thread(new Runnable() {
        private long startTime = System.currentTimeMillis();
        public void run() {
            while (gameState == GameState.Playing) {                
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        tvTime.setText(""+((System.currentTimeMillis()-startTime)/1000));
                    }
                });
                try {
                    Thread.sleep(1000);
                } 
                catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    });
    th.start();
}
4

4 回答 4

54

UserInterface 只能由 UI 线程更新。您需要一个Handler来发布到 UI 线程:

private void startTimerThread() {
    Handler handler = new Handler();
    Runnable runnable = new Runnable() {
        private long startTime = System.currentTimeMillis();
        public void run() {
            while (gameState == GameState.Playing) {  
                try {
                    Thread.sleep(1000);
                }    
                catch (InterruptedException e) {
                    e.printStackTrace();
                }
                handler.post(new Runnable(){
                    public void run() {
                       tvTime.setText("" + ((System.currentTimeMillis() - this.startTime) / 1000));
                }
            });
            }
        }
    };
    new Thread(runnable).start();
}
于 2012-10-03T21:21:00.113 回答
32

或者,您也可以在您想要更新 UI 元素时在您的线程中执行此操作:

runOnUiThread(new Runnable() {
    public void run() {
        // Update UI elements
    }
});
于 2012-10-03T21:23:50.397 回答
2

作为一个选项,使用runOnUiThread()来更改主线程中的视图属性。

  runOnUiThread(new Runnable() {
        @Override
        public void run() {       
                textView.setText("Stackoverflow is cool!");
        }
    });
于 2017-03-29T23:12:20.760 回答
1

您不能从非 UI 线程访问 UI 元素。尝试setText(...)用另一个包围调用Runnable,然后查看View.post(Runnable)方法。

于 2012-10-03T21:21:13.910 回答