Android Kotlin基礎講座 05.4: LiveDataの変換

Android Kotlin基礎講座

タスク:タイマーを追加する

このタスクでは、アプリにカウントダウンタイマーを追加します。単語が空になったらゲームを終了させるのではなく、タイマーが終了したらゲームを終了するようにします。Androidはタイマーを実装する際に使えるCountDownTimerというユーティリティクラスを提供しています。

タイマーがコンフィグレーション変化によって破棄されないようにするためんpロジックをGameViewModelに追加します。フラグメントにはタイマーが時間を刻むごとにタイマーのテキストビューを更新するためのコードが含まれます。

以下の手順に従って、GameViewModelクラスに実装してください。

  1. タイマー用の定数を保持するための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

}
  1. タイマーのカウントダウン時間を保存するために、_currentTimeというMutableLiveDataメンバ変数と、currentTimeというバッキングプロパティを追加してください。
// Countdown time
private val _currentTime = MutableLiveData<Long>()
val currentTime: LiveData<Long>
   get() = _currentTime
  1. CountDownTimer型のtimerというprivateなメンバ変数を追加してください。初期化エラーは次のステップで解消します。
private val timer: CountDownTimer
  1. 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()
  1. onTick()コールバックメソッドを実装してください。これはインターバル毎、または毎ティックごとに呼び出されます。渡されたパラメーターであるmillisUntilsFinishedを使い、_currentTimeを更新してください。millisUntilFinishedはタイマーが終わるまでの時間をミリ秒で表したものです。millisUntilFinishedを秒単位に変換し、_currentTimeに代入します。
override fun onTick(millisUntilFinished: Long)
{
   _currentTime.value = millisUntilFinished/ONE_SECOND
}
  1. onFinish()コールバックメソッドはタイマーが終わったときに呼び出されます。_currentTimeを更新し、ゲーム終了イベントのトリガーとなるように実装してください。
override fun onFinish() {
   _currentTime.value = DONE
   onGameFinish()
}
  1. 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)
}
  1. onCleared()メソッド内で、メモリリークを起こさないようにするために、タイマーを停止してください。ログ文はもう必要ないので、削除しても大丈夫です。onCleared()メソッドはViewModelが破棄される前に呼び出されます。
override fun onCleared() {
   super.onCleared()
   // Cancel the timer
   timer.cancel()
}
  1. アプリを起動し、ゲームをプレイしてください。60秒待ち、ゲームが自動で終了されることを確認してください。しかしタイマーテキストは画面上には表示されていません。次はこれを直していきます。

コメント

プロフィール

プロフィール
コードラボJP

大学卒業後SEに就職、現在は退職しフリーランスとして活動中。
『初心者でも挫折せずに一人でプログラミングを学べる』をモットーに、コードラボJPを開設
お問い合わせ等はcodelabsjp@gmail.comまで

コードラボJPをフォローする
タイトルとURLをコピーしました