これまではAndroidでタイマー機能を実装するのに、Handler
とRunnable
を使ってやっていたかと思います。
1 2 3 4 5 6 7 8 9 10 11 |
private Handler handler = new Handler(); handler.postDelayed(new Runnable() { @Override public void run() { /* do what you need to do */ foobar(); /* and here comes the "trick" */ handler.postDelayed(this, 100); } }, 100); |
僕は使ったことはないですが、java.util.Timer
やjava.util.TimerTask
を使ってやる方法もあるようです。
と思ったら、やったらだめ!と主張してるサイトもあるようですね。
さて、本題ですが、今はRxという便利なライブラリがあるので、バックグラウンドの処理はこれに置き換えてしまいましょう。
下記がソースコードです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
private static final int TIMER_DURATION = 30; Observable.interval(1, TimeUnit.SECONDS) .take(TIMER_DURATION) .map(aLong -> TIMER_DURATION - aLong) .subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Subscriber<Long>() { @Override public void onCompleted() { //Timer終了後 } @Override public void onError(Throwable e) { //エラー発生時 } @Override public void onNext(Long aLong) { //毎秒ここが呼ばれる } }); |
今回のRxはVer1.xです。2.xでもそのまま使えると思いますがちょっとまだ試せていません。
解説ですが、
- Observableの
interval
オペレーターで、毎秒メッセージを発信するストリームを作成する。 take
オペレーターで、ストリームを先頭から指定した件数までに指定する。ここでは 30map
オペレーターで、発信する値を編集する。内容はTIMER_DURATION - aLong
で、aLongは呼ばれるたびにTIMER_DURATION
まで増えるので、結果的に1ずつ減ったLongが送信される。subscribe
でタイマー処理を起動する。onNext
にて、毎秒の処理を記載する。ここでログを出するとカウンターが減っていく様子が確認できる。onCompleted
にて、タイマー終了後の処理を記載する。タイマー処理後の処理はここで書くと良い。
以上です。