Android在Thread和Runnable中更新TextView

时间:2021-06-05 17:29:01

I want to make a simple timer in Android that updates a TextView every second. It simply counts seconds like in Minesweeper.

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

The problem is when i ignore the tvTime.setText(...) (make it //tvTime.setText(...), in LogCat will be printed the following number every second. But when i want to set this number to a TextView (created in another Thread), the program crashes.

问题是当我忽略tvTime.setText(...)(使它成为//tvTime.setText(...)时,在LogCat中将每秒打印下面的数字。但是当我想将这个数字设置为a时TextView(在另一个Thread中创建),程序崩溃。

Does anyone have an idea how to solve this easily?

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

Here's the code (method is called on startup):

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

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();
}

EDIT:

编辑:

Finally, I got it. Here is the solution, for those who are interested in.

最后我得到了它。对于那些感兴趣的人来说,这是解决方案。

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 个解决方案

#1


45  

The UserInterface can only be updated by the UI Thread. You need a Handler, to post to the UI Thread:

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();
}

#2


27  

Alternatively, you can also just do this in your thread whenever you want to update a UI element:

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

runOnUiThread(new Runnable() {
    public void run() {
        // Update UI elements
    }
});

#3


0  

You cannot access UI elements from non-UI threads. Try surrounding the call to setText(...) with another Runnable and then look into the View.post(Runnable) method.

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

#4


0  

As an option use runOnUiThread() to change de views properties in the main thread.

作为选项,使用runOnUiThread()来更改主线程中的de views属性。

  runOnUiThread(new Runnable() {
        @Override
        public void run() {       
                textView.setText("* is cool!");
        }
    });

#1


45  

The UserInterface can only be updated by the UI Thread. You need a Handler, to post to the UI Thread:

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();
}

#2


27  

Alternatively, you can also just do this in your thread whenever you want to update a UI element:

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

runOnUiThread(new Runnable() {
    public void run() {
        // Update UI elements
    }
});

#3


0  

You cannot access UI elements from non-UI threads. Try surrounding the call to setText(...) with another Runnable and then look into the View.post(Runnable) method.

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

#4


0  

As an option use runOnUiThread() to change de views properties in the main thread.

作为选项,使用runOnUiThread()来更改主线程中的de views属性。

  runOnUiThread(new Runnable() {
        @Override
        public void run() {       
                textView.setText("* is cool!");
        }
    });