タイマーアプリを作ってみる
2015/09/22
とりあえず、シンプルにタイマーアプリでも作ってみる。
あらかじめ用意されているクラスに、ちょうど CountDownTimer クラスがあるので、それを用いることにする。
ただし、CountDownTimerに対して指示できるのはStartとCancelだけ。
Pauseが出来ないので、そこらへんを考慮する必要がある。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
// コンストラクタの第一引数はカウントダウンする時間 // 第二引数は onTick が呼ばれる間隔 // それぞれ ミリ秒単位 で指定する CountDownTimer timer = new CountDownTimer(3000, 1000){ @Override public void onFinish(){ // タイムアップ時の処理をここに記述 // この場合start()を実行してから3秒後に呼ばれる } @Override public void onTick(long millisUntilFinished){ // このメソッドの仮引数では残り時間が渡される // また、コンストラクタの第二引数で指定した間隔で呼ばれる // この場合1秒ごとに呼ばれる } }; timer.start(); // カウントダウン開始 timer.cancel(); // カウントダウン停止 |
cancel() を実行するとタイマーを止めることが出来るが、
再び start() を呼んでも残り時間はまた3秒からになってしまう。
そこで、 onTick で取得できる残り時間を、別に控えておく方法をとることにした。
pauseをしたいときはcancel()の後、一度インスタンスを破棄。
pauseから再開するときは、calcelの直前まで控えていた残り時間を使って新しいCountDownTimerを作成し start()。
ただ、onTick が呼ばれる間隔が長いとそれだけ誤差も大きくなるので、短めに設定しないとタイマーとして微妙な感じになりそう。
追記
Pause機能などを実装したクラスを作ってみた。
とりあえず、動くことは確認したけど、実際のお仕事としてプログラムを書いたことがないので、そういう観点から見るとどうなのかわからない。実用に耐えるようにするにはもっと考えることがありそう。
「ここがおかしい」という箇所を指摘していただけると助かります。
また、変数名やコメントなどそのままにしてありますが、コメントは自分用なので何のことかわからないところもあるかもしれません。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
package com.kiskksk.kcdt; import android.os.CountDownTimer; import android.support.annotation.NonNull; public class KCDTimer { /** * タイマーの設定時間。ミリ秒 * 0の場合。タイマーは開始しない。 */ private long mMillisInFuture; /** * onTickの呼び出し間隔。ミリ秒。 * 最短で10までの値を指定できるが、短すぎるとほかの処理に影響が出そう * 初期値は1000 */ private long mCountDownInterval = 1000; /** * pauseからの再スタートに利用 * 残り時間はinterval毎に取得されるので、intervalよりも短い間隔は切り上げられた時間になる(若干延びる)。 */ private long mMillisUntilFinished; /** * タイマー起動中ならtrue */ private boolean mTimerWorking; /** * カウントダウンタイマー、cancel用にインスタンス変数で持つ */ private CountDownTimer mTimer; /** * タイマーのコールバックを橋渡しするためのリスナ */ private KCDTimerReceivedListener mListener; /** * CountDownTimerのコールバックをそのまま渡すリスナ */ public interface KCDTimerReceivedListener{ void onFinish(); void onTick(long millisUntilFinished); } /** * リスナは必須 * @param millisInFuture 設定時間。ミリ秒 * @param countDownInterval コールバックの間隔。ミリ秒 * @param listener コールバック用リスナ */ public KCDTimer(long millisInFuture, long countDownInterval,@NonNull KCDTimerReceivedListener listener){ setMillisInFuture(millisInFuture); setCountDownInterval(countDownInterval); this.mListener = listener; } /** * カウントダウンを開始する。ポーズされている場合は途中からカウントダウン。 * @return 設定時間(残り時間mMillisUntilFinished)が0秒、listerがnull、 * もしくは、既にタイマーが起動中の場合、開始せずに false を返す。 * 今回の呼び出しでタイマーを開始した場合、戻り値はtrue。 */ public boolean start(){ if(mListener == null || mTimerWorking || mMillisUntilFinished==0) return false; mTimerWorking = true; mTimer = null; mTimer = new CountDownTimer(mMillisUntilFinished, mCountDownInterval){ @Override public void onTick(long l) { mListener.onTick(l); mMillisUntilFinished = l; } @Override public void onFinish() { mTimerWorking = false; // 0までいったら残り時間を初期化する?しない方がいいのか? // とりあえず今は初期化しない // 初期化しない場合でも、タイムアップ後には設定しなおす必要がある(でないとインターバル分残ってしまう) // ので、mMillisUntilFinishedの値を0にしておく mMillisUntilFinished = 0; mListener.onFinish(); } }.start(); return true; } /** * タイマーを一時停止する * @return 残り時間 */ public long pause(){ stopTimer(); return this.mMillisUntilFinished; } /** * タイマーを停止して、状態を初期化する * @return 残り時間(設定時間と同値) */ public long reset(){ stopTimer(); this.mMillisUntilFinished = this.mMillisInFuture; return this.mMillisUntilFinished; } /** * timer=nullを入れると複数回のreset呼び出しでぬるぽになりそうなのでここでは行わない */ private void stopTimer(){ if(mTimer!=null) mTimer.cancel(); mTimerWorking = false; } /** * タイマーへの参照を破棄する。動いている場合は止めてから破棄 */ public void release(){ stopTimer(); mTimer = null; } /** * 設定時間を指定する。0をセットした場合、startを呼んでも開始しない。 * @param millisInFuture 負数の場合、0がセットされる */ public void setMillisInFuture(long millisInFuture){ this.mMillisInFuture = (millisInFuture > 0) ? millisInFuture : 0; this.mMillisUntilFinished = this.mMillisInFuture; } /** * @param countDownInterval 10未満の場合、10が設定される */ public void setCountDownInterval(long countDownInterval){ this.mCountDownInterval = (countDownInterval>=10) ? countDownInterval : 10; } /** * タイマーが起動中か判定する * @return true:起動中, false:起動していない */ public boolean isTimerWorking(){ return mTimerWorking; } /** * このインスタンス(KCDTimer)が保持している、タイマーの残り時間を返却する * 画面切り替えなどで、Activityの変数が初期化されていた場合などに使えるかも * @return 残り時間 */ public long getMillisUntilFinished(){ return this.mMillisUntilFinished; } // /** 今のところ使わないっぽいのでコメントアウト // * リスナーの動作を変更する場合、新しいリスナーをセットする // * @param listener 新しいリスナ // */ // public void setListener(KCDTimerReceivedListener listener){ // this.mListener = listener; // } } |
関連記事
-
-
Android Serviceのメモ。onBind,onRebind,onUnbindが呼ばれる条件
onBindやonUnbindが呼ばれるタイミングが紛らわしかったのでメモ。 個 …
-
-
AndroidStudioでコピペする方法。デフォルトではクリップボードから貼り付けできない
AndroidStudioでは外部アプリからのコピペがデフォルトだと出来ない。 …
-
-
Androidアプリの「デフォルトで起動」設定の初期化
Androidでは、処理ごとに担当するアプリが決まっています。その都度、必要なア …
-
-
Android「標準ブラウザ」から「Chrome」へブックマークを移行する方法
追記 久々に確認してみたところ、この記事の方法は出来なくなっていました。[現時点 …
-
-
Android4.3以下の場合、標準ブラウザは無効推奨らしいのでその方法。
先日、ブックマークについての記事を書きました。 その際、親が利用していたのは「標 …
スポンサーリンク
週間人気記事
Android Serviceのメモ。onBind,onRebind,onUnbindが呼ばれる条件
クリップボードの内容を取得しよう→_crtisvalidheappointerエラーで落ちる