CountDownTimer クラスの基本的な使い方としては
CountDownTimer myCountDownTimer
= new CowntDownTimer(long millisInFuture, long countDownInterval)
上記の様にインスタンス化の際に、カウントダウン時間(millisInFuture)、インターバル時間(countDownInterval)をミリ秒で渡します。
インターバル時間は、onTick()メソッドに記載した処理が行われる間隔になります。
秒単位のタイマーであれば、残り時間の表示を1秒に1回書き換えればいいので、インターバル時間は、1秒 = 1000ミリ秒の指定で問題ないように思われます。
しかし、実際に1000ミリ秒を指定すると、タイマー終了時の時間表示が“1”で止まってしまいます。
何故なのか解明するため、ログをとってみました。
ログの取り方
onTick()メソッド内に、下記の行を追加します。
onTick()毎に、残り時間がログに出力されます。
Log.i("MainActivity", "残り時間 = " + String.valueOf(millisUntilFinished));
インターバル時間を、1000, 100, 10, 1 と変えて、試してみました。
① 1000
② 100
③ 10
④ 1
これらから、以下の様に推測しました。
- インターバルは、ミリ秒単位で正確に刻まれている訳ではなく、誤差がある。(1000, 100 ミリ秒インターバルでは、1回毎に10ミリ秒程度、10, 1 ミリ秒インターバルでは、1回毎に10~20ミリ秒程度)
- 最後の1回の処理は飛ばされている?(④の1ミリ秒を除けば、もう1回処理されても良さそうな時間が残っているのに、されていない。)
これによって起こりそうな問題は、以下の2つが考えられます。
① 誤差による処理の抜け落ち
例えば、秒単位で時間を表示する場合、インターバルが1000ミリ秒だと、1005 → 895 のようにonTickが刻まれてしまう可能性があり、その際は秒数の表示が 10 → 8 となり、9秒が抜け落ちる。
② 最後の秒(0秒)が表示されない
冒頭の通り。これを防ぐためには、
① → 誤差を考慮に入れて、短めのインターバル時間を設定する。
② → これも考慮に入れて、さらに短めのインターバル時間を表示する...というのも手ですが、最後に表示する値は、onFinish()メソッドに記載する、とした方が、ムダが無く確実な気がします。
先日のカウントダウンタイマーの場合、以下の様にonFinish()内に、textViewに“0”を表示する処理を追記しました。
// カウントダウン終了後の処理 @Override public void onFinish() { toggleButton.setChecked(false); // toggleボタンをオフにする textView.setText("0"); // 0を表示 }
0 件のコメント:
コメントを投稿