Android Kotlin基礎講座 05.4: LiveDataの変換
目次
タスク:タイマーを追加する
このタスクでは、アプリにカウントダウンタイマーを追加します。単語が空になったらゲームを終了させるのではなく、タイマーが終了したらゲームを終了するようにします。Androidはタイマーを実装する際に使えるCountDownTimerというユーティリティクラスを提供しています。
タイマーがコンフィグレーション変化によって破棄されないようにするためんpロジックをGameViewModelに追加します。フラグメントにはタイマーが時間を刻むごとにタイマーのテキストビューを更新するためのコードが含まれます。
以下の手順に従って、GameViewModelクラスに実装してください。
- タイマー用の定数を保持するためのcompanionオブジェクトを作成してください。
companion object {
// Time when the game is over
private const val DONE = 0L
// Countdown time interval
private const val ONE_SECOND = 1000L
// Total time for the game
private const val COUNTDOWN_TIME = 60000L
}
- タイマーのカウントダウン時間を保存するために、_currentTimeというMutableLiveDataメンバ変数と、currentTimeというバッキングプロパティを追加してください。
// Countdown time
private val _currentTime = MutableLiveData<Long>()
val currentTime: LiveData<Long>
get() = _currentTime
- CountDownTimer型のtimerというprivateなメンバ変数を追加してください。初期化エラーは次のステップで解消します。
private val timer: CountDownTimer
- initブロックの中で、タイマーを初期化し、スタートしてください。合計時間であるCOUNTDOWN_TIMEを渡してください。インターバル時間にはONE_SECONDを使います。onTick()とonFinish()コールバックメソッドをオーバーライドし、タイマーをスタートさせてください。
// Creates a timer which triggers the end of the game when it finishes
timer = object : CountDownTimer(COUNTDOWN_TIME, ONE_SECOND) {
override fun onTick(millisUntilFinished: Long) {
}
override fun onFinish() {
}
}
timer.start()
- onTick()コールバックメソッドを実装してください。これはインターバル毎、または毎ティックごとに呼び出されます。渡されたパラメーターであるmillisUntilsFinishedを使い、_currentTimeを更新してください。millisUntilFinishedはタイマーが終わるまでの時間をミリ秒で表したものです。millisUntilFinishedを秒単位に変換し、_currentTimeに代入します。
override fun onTick(millisUntilFinished: Long)
{
_currentTime.value = millisUntilFinished/ONE_SECOND
}
- onFinish()コールバックメソッドはタイマーが終わったときに呼び出されます。_currentTimeを更新し、ゲーム終了イベントのトリガーとなるように実装してください。
override fun onFinish() {
_currentTime.value = DONE
onGameFinish()
}
- nextWord()メソッドを単語リストが空になったときにゲームを終了させるのではなく、単語をリセットするように更新してください。
private fun nextWord() {
// Shuffle the word list, if the list is empty
if (wordList.isEmpty()) {
resetList()
} else {
// Remove a word from the list
_word.value = wordList.removeAt(0)
}
- onCleared()メソッド内で、メモリリークを起こさないようにするために、タイマーを停止してください。ログ文はもう必要ないので、削除しても大丈夫です。onCleared()メソッドはViewModelが破棄される前に呼び出されます。
override fun onCleared() {
super.onCleared()
// Cancel the timer
timer.cancel()
}
- アプリを起動し、ゲームをプレイしてください。60秒待ち、ゲームが自動で終了されることを確認してください。しかしタイマーテキストは画面上には表示されていません。次はこれを直していきます。