2013年8月30日金曜日

Android CountDownTimerを使う

 こんにちは。scarvizです。

 今回はカウントダウン式のタイマーを実装する時に、CountDownTimerを使う方法についてです。
 CountDownTimerを継承したクラスを用意するだけで簡単に実装できますが、ちょっと気をつけないといけないことがあるので、一緒に紹介しようと思います。




■CountDownTimerを継承させたクラスを用意する
 まずはCountDownTimerを継承させたクラスを用意します。

/**
 * カウントダウンタイマークラス
 */
public class CDTimer extends CountDownTimer {

 public CDTimer(long millisInFuture, long countDownInterval) {
  super(millisInFuture, countDownInterval);
 }

 @Override
 public void onFinish() {
  // タイマー終了時処理
 }

 @Override
 public void onTick(long millisUntilFinished) {
  // countDownIntervalで指定した間隔で呼ばれる定期処理
 }

}

 onTickメソッドは指定した間隔で呼ばれます。onFinishメソッドはタイマー終了時に呼ばれます。
 例えば、onTickメソッドでは、残り時間の画面描画処理を、onFinishメソッドでは、タイマー終了時にアラームを鳴らす処理などを実装します。

■タイマーの開始、停止
 タイマーの開始は次のように行います。

 CDTimer mCDTimer;
 mCDTimer = new CDTimer(timer, interval);
 mCDTimer.start();

 カウントダウンタイマークラスのコンストラクタの引数に、カウントダウンする時間(timer)と、onTickメソッドを呼ぶ間隔(interval)を渡します。どちらの値もミリ秒単位です。

 タイマーの停止は次のように行います。

 mCDTimer.cancel();
 mCDTimer = null;

 cancelメソッドを呼ぶことでタイマーを停止します。ただし、一度cancelメソッドを呼ぶと再利用は出来なくなります。次にカウントダウンをさせたい場合はインスタンスの再生成を行う必要があります。

■カウントダウン間隔
 以上でタイマー実装は完成です。簡単ですね。試しにタイマー時間1分、定期処理間隔1秒で、画面に残り時間を秒単位で表示するようにして実行してみましょう。
 実行してみましたか?何か変ですよね。最後の1秒でもたつくと思います。実装の仕方によっては0までカウントダウンしません。

 試しにLogcatに進行状況を出力してみましょう。次のように実装してみました。

 public CDTimer(long millisInFuture, long countDownInterval) {
  super(millisInFuture, countDownInterval);
  Log.d("TimerActivity", "start timer : " + millisInFuture + ", interval : " + countDownInterval);
 }

 @Override
 public void onTick(long millisUntilFinished) {
  // countDownIntervalで指定した間隔で呼ばれる定期処理
  int min = (int)((millisUntilFinished / 1000) / 60);
  int sec = (int)((millisUntilFinished / 1000) % 60);
  
  String timer = String.format("%1$02d:%2$02d", min, sec);
  Log.d("TimerActivity", "trick timer : " + millisUntilFinished + ", " + timer);
 }

実行結果:
08-30 01:17:30.158: DEBUG/TimerActivity(523): start timer : 60000, interval : 1000
08-30 01:17:30.289: DEBUG/TimerActivity(523): trick timer : 59871, 00:59
08-30 01:17:31.313: DEBUG/TimerActivity(523): trick timer : 58847, 00:58
08-30 01:17:32.338: DEBUG/TimerActivity(523): trick timer : 57825, 00:57
(省略)
08-30 01:18:24.079: DEBUG/TimerActivity(523): trick timer : 6083, 00:06
08-30 01:18:25.159: DEBUG/TimerActivity(523): trick timer : 5000, 00:05
08-30 01:18:26.219: DEBUG/TimerActivity(523): trick timer : 3944, 00:03
08-30 01:18:27.268: DEBUG/TimerActivity(523): trick timer : 2887, 00:02
08-30 01:18:28.339: DEBUG/TimerActivity(523): trick timer : 1821, 00:01

 基本的に指定した間隔時間でonTickが呼ばれますが、最後の1回が呼ばれませんでした。そのため、2秒あまり更新無くタイマーが終了するようになっています。
 試しに間隔時間を短くしてみましょう。500ミリ秒に変更し、実行してみると以下のようになりました。

実行結果:
08-30 01:49:10.562: DEBUG/TimerActivity(546): start timer : 60000, interval : 500
08-30 01:49:10.763: DEBUG/TimerActivity(546): trick timer : 59800, 00:59
08-30 01:49:11.322: DEBUG/TimerActivity(546): trick timer : 59253, 00:59
08-30 01:49:11.863: DEBUG/TimerActivity(546): trick timer : 58704, 00:58
08-30 01:49:12.382: DEBUG/TimerActivity(546): trick timer : 58188, 00:58
08-30 01:49:12.902: DEBUG/TimerActivity(546): trick timer : 57666, 00:57
08-30 01:49:13.412: DEBUG/TimerActivity(546): trick timer : 57157, 00:57
08-30 01:49:13.928: DEBUG/TimerActivity(546): trick timer : 56639, 00:56
08-30 01:49:14.442: DEBUG/TimerActivity(546): trick timer : 56129, 00:56
(省略)
08-30 01:50:03.913: DEBUG/TimerActivity(546): trick timer : 6657, 00:06
08-30 01:50:04.424: DEBUG/TimerActivity(546): trick timer : 6142, 00:06
08-30 01:50:05.003: DEBUG/TimerActivity(546): trick timer : 5567, 00:05
08-30 01:50:05.534: DEBUG/TimerActivity(546): trick timer : 5032, 00:05
08-30 01:50:06.108: DEBUG/TimerActivity(546): trick timer : 4458, 00:04
08-30 01:50:06.623: DEBUG/TimerActivity(546): trick timer : 3943, 00:03
08-30 01:50:07.142: DEBUG/TimerActivity(546): trick timer : 3424, 00:03
08-30 01:50:07.646: DEBUG/TimerActivity(546): trick timer : 2920, 00:02
08-30 01:50:08.223: DEBUG/TimerActivity(546): trick timer : 2343, 00:02
08-30 01:50:08.793: DEBUG/TimerActivity(546): trick timer : 1776, 00:01
08-30 01:50:09.293: DEBUG/TimerActivity(546): trick timer : 1271, 00:01
08-30 01:50:09.867: DEBUG/TimerActivity(546): trick timer : 699, 00:00

 やはり最後の1回が呼ばれませんでした。ただ、描画上は期待した動きになりそうです。1秒単位でカウントダウンさせる場合は、1秒未満の間隔時間を指定する方が良さそうです。

0 件のコメント:

コメントを投稿