ストップウォッチを作成するためにタイマーを使用しています。タイマーは、整数値を増やすことで機能します。次に、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インスタンスを作成する必要はありません。
TimerTaskはRunnableを実装し、これによりスレッドになります。いくつかの作業を行わずに、メインUIスレッドを別のスレッドから直接更新することはできません。できることの1つは、非同期タスクを使用してタイマーを作成し、UIを更新する更新を1秒ごとに公開することです。
私はStopWatch.time
は、TextViewへの静的またはパブリック参照です。これを行う代わりに、 BroadcastReceiver を実装して、タイマー(別のスレッドから実行される)とTextViewの間で通信する必要があります。
次のユーティリティを使用できます。
/**
* 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);
ハンドラーを使用できます。
このコードカウンターを1秒ごとに増やしますおよびshow and updateカウンター値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);
}
}