Android Kotlin基礎講座 05.2: LiveDataとLiveData observers
目次
タスク:GameViewModelにLiveDataを追加する
LiveDataはライフサイクル対応の監視可能なデータホルダークラスです。例として、GuessTheWordアプリの現在の得点をLiveDataでラッピングできます。この記事では、LiveDataのいくつかの特徴について学習します。
- LiveDataは監視可能です。これはLiveDataオブジェクトによって保持されているデータに変更があったときにオブザーバーに通知されることを意味しています。
- LiveDataはデータを保持します。LiveDataはどんなデータにも用いることができるラッパーです。
- LiveDataはライフサイクル対応です。オブザーバーをLiveDataに取り付けると、オブザーバーはLifecycleOwner(通常はアクティブやフラグメント)と紐づけられます。
LiveDataはSTARTEDやRESUMEDのようなアクティブなライフサイクル状態の中にあるオブザーバーのみを更新します。LiveDataと監視についてはこちらから詳細が見れます。
このタスクではどのようにして様々なデータ型をLiveDataオブジェクトにラッピングするのかを、GameViewModelの現在の得点と現在の単語をLiveDataに変換することで学習していきます。後のタスクではこれらのLiveDataにオブザーバーを追加し、LiveDataを監視する方法を学習します。
ステップ1:得点と単語をLiveDataを使うようにする
- screens/gameパッケージの下のGameViewModelファイルを開いてください。
- scoreとword変数の型をMutableLiveDataに変更してください。
MutableLiveDataとは値が変更可能なLiveDataです。
MutableLiveDataは汎用クラスなので、それが保持するデータの型を指定する必要があります。
// The current word
val word = MutableLiveData<String>()
// The current score
val score = MutableLiveData<Int>()
- GameViewModel中のinitブロックの中で、scoreとwordを初期化してください。LiveData変数の値を変更するためにはその変数に対してsetValue()メソッドを使用します。Kotlinではvalueプロパティを用いてsetValue()を呼び出します。
init {
word.value = ""
score.value = 0
...
}
ステップ2:LiveDataオブジェクトの参照を更新する
score変数とword変数は現在LiveData型になっています。このステップでは、これらの変数の参照をvalueプロパティを用いて変更します。
- GameViewModel中のonSkip()メソッドの中のscoreをscore.valueに変更してください。scoreがnullになり得ることに関するエラーが表示されると思います。このエラーは次で解消します。
- エラーを解消するために、onSkip()の中でscore.valueに対するnullチェックを追加してください。その後、minus()関数をscoreに対して呼び出します。これはnull安全に減算できる機能です。
fun onSkip() {
score.value = (score.value)?.minus(1)
nextWord()
}
- 同様にしてonCorrect()メソッドを更新してください。scoreに対してnullチェックを追加し、plus()関数を用いてください。
fun onCorrect() {
score.value = (score.value)?.plus(1)
nextWord()
}
- GameViewModel中のnextWord()メソッドの中のwordをword.valueに変更してください。
private fun nextWord() {
if (!wordList.isEmpty()) {
//Select and remove a word from the list
word.value = wordList.removeAt(0)
}
}
- GameFragment中のupdateWordText()メソッド中で、viewModel.wordへの参照をviewmodel.word.valueに変更してください。
/** Methods for updating the UI **/
private fun updateWordText() {
binding.wordText.text = viewModel.word.value
}
- GameFragment中のupdateScoreText()メソッド中のviewModel.scoreへの参照をviewModel.score.valueに変更してください。
private fun updateScoreText() {
binding.scoreText.text = viewModel.score.value.toString()
}
- GameViewModel中のgameFinished()メソッド中のviewModel.scoreへの参照をviewModel.score.valueに変更してください。さらにnull安全チェックを追加してください。
private fun gameFinished() {
Toast.makeText(activity, "Game has just finished", Toast.LENGTH_SHORT).show()
val action = GameFragmentDirections.actionGameToScore()
action.score = viewModel.score.value?:0
NavHostFragment.findNavController(this).navigate(action)
}
- コードにエラーが発生していないことを確認してください。コンパイルしてアプリを起動してください。アプリの機能は以前と同じはずです。