Обновление Android TextView в потоке и Runnable
Я хочу сделать простой таймер в Android, который обновляет TextView каждую секунду. Он просто подсчитывает секунды, как в Minesweeper.
Проблема в том, что я игнорирую 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();
}
EDIT:
Наконец, я понял.
Вот решение для тех, кто интересуется.
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();
}
Ответы
Ответ 1
Пользовательский интерфейс может обновляться только через поток пользовательского интерфейса. Вам нужно Handler, чтобы опубликовать его в теме пользовательского интерфейса:
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
Кроме того, вы можете просто сделать это в своем потоке всякий раз, когда хотите обновить элемент пользовательского интерфейса:
runOnUiThread(new Runnable() {
public void run() {
// Update UI elements
}
});
Ответ 3
Вы не можете получить доступ к элементам пользовательского интерфейса из потоков, отличных от UI. Попробуйте связать вызов setText(...)
с другим Runnable
, а затем просмотрите метод View.post(Runnable)
.
Ответ 4
В качестве опции используйте runOnUiThread() для изменения свойств представлений в основном потоке.
runOnUiThread(new Runnable() {
@Override
public void run() {
textView.setText("Stackoverflow is cool!");
}
});