[英]Android timer updating a textview (UI)
我正在使用計時器來創建秒表。 計時器通過增加 integer 值來工作。 然后我想通過不斷更新 textview 在活動中顯示這個值。
這是我嘗試更新活動的 textview 的服務中的代碼:
protected static void startTimer() {
isTimerRunning = true;
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
elapsedTime += 1; //increase every sec
StopWatch.time.setText(formatIntoHHMMSS(elapsedTime)); //this is the textview
}
}, 0, 1000);
}
我在錯誤的線程中更新 UI 時遇到了某種錯誤。
如何調整我的代碼以完成不斷更新 textview 的任務?
protected static void startTimer() {
isTimerRunning = true;
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
elapsedTime += 1; //increase every sec
mHandler.obtainMessage(1).sendToTarget();
}
}, 0, 1000);
}
public Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
StopWatch.time.setText(formatIntoHHMMSS(elapsedTime)); //this is the textview
}
};
上面的代碼將工作...
注意:處理程序必須在您的主線程中創建,以便您可以修改 UI 內容。
您應該使用Handler
每 X 秒更新一次 UI。 這是另一個顯示示例的問題: 重復一個有時間延遲的任務?
您的方法不起作用,因為您正在嘗試從非 UI 線程更新 UI。 這是不允許的。
StopWatch.time.post(new Runnable() {
StopWatch.time.setText(formatIntoHHMMSS(elapsedTime));
});
此代碼塊基於 Handler,但您不需要創建自己的 Handler 實例。
您可以使用以下實用程序:
/**
* Created by Ofek on 19/08/2015.
*/
public class TaskScheduler extends Handler {
private ArrayMap<Runnable,Runnable> tasks = new ArrayMap<>();
public void scheduleAtFixedRate(final Runnable task,long delay,final long period) {
Runnable runnable = new Runnable() {
@Override
public void run() {
task.run();
postDelayed(this, period);
}
};
tasks.put(task, runnable);
postDelayed(runnable, delay);
}
public void scheduleAtFixedRate(final Runnable task,final long period) {
Runnable runnable = new Runnable() {
@Override
public void run() {
task.run();
postDelayed(this, period);
}
};
tasks.put(task, runnable);
runnable.run();
}
public void stop(Runnable task) {
Runnable removed = tasks.remove(task);
if (removed!=null) removeCallbacks(removed);
}
}
然后在由 UI 線程運行的代碼中的任何地方,您都可以像這樣簡單地使用它:
TaskScheduler timer = new TaskScheduler();
timer.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
time.setText(simpleDateFormat.format(GamePlay.instance().getLevelTime()));
}
},1000);
你可以使用處理程序。
此代碼每秒增加一個計數器,並在textView上顯示和更新計數器值。
public class MainActivity extends Activity {
private Handler handler = new Handler();
private TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView) findViewById(R.id.text);
startTimer();
}
int i = 0;
Runnable runnable = new Runnable() {
@Override
public void run() {
i++;
textView.setText("counter:" + i);
startTimer();
}
};
public void startTimer() {
handler.postDelayed(runnable, 1000);
}
public void cancelTimer() {
handler.removeCallbacks(runnable);
}
@Override
protected void onStop() {
super.onStop();
handler.removeCallbacks(runnable);
}
}
TimerTask 實現了 Runnable,這將使它成為一個線程。 如果不做一些工作,您無法直接從不同的線程更新主 UI 線程。 您可以做的一件事是使用 Async Task 創建計時器並每秒發布一次更新,以更新 UI。
我假設StopWatch.time
是一些 static 或對您的 TextView 的公共引用。 而不是這樣做,您應該實現BroadcastReceiver以在您的計時器(從單獨的線程運行)和您的 TextView 之間進行通信。
我用這種方式:
String[] array = {"man", "for", "think"};
int j;
然后添加更多onCreate
:
TextView t = findViewById(R.id.textView);
new CountDownTimer(5000,1000) {
@Override
public void onTick(long millisUntilFinished) {}
@Override
public void onFinish() {
t.setText("I " + array[j] + " You");
j++;
if (j == array.length - 1) j = 0;
start();
}
}.start();
timer.schedule(new TimerTask() {
@Override
public void run() {
//your actions
}
},1*1000);//1 sec
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.