この Codelab は、Android Kotlin の基礎コースの一部です。このコースを最大限に活用するには、Codelab を順番に進めることをおすすめします。コースのすべての Codelab は、Android Kotlin の基礎の Codelab のランディング ページに一覧表示されています。
はじめに
前の Codelab では、GuessTheWord アプリで ViewModel を使用して、デバイスの構成変更後もアプリのデータを維持できるようにしました。この Codelab では、LiveData を ViewModel クラスのデータと統合する方法を学びます。LiveData は Android アーキテクチャ コンポーネントの 1 つで、基盤となるデータベースが変更されたときにビューに通知するデータ オブジェクトを構築できます。
LiveData クラスを使用するには、アプリのデータの変更を監視する「オブザーバー」(アクティビティやフラグメントなど)を設定します。LiveData はライフサイクル対応であるため、アクティブなライフサイクルの状態にあるアプリ コンポーネント オブザーバーのみを更新します。
前提となる知識
- Kotlin で基本的な Android アプリを作成する方法。
- アプリのデスティネーション間を移動する方法。
- アクティビティとフラグメントのライフサイクル。
- アプリで
ViewModelオブジェクトを使用する方法。 ViewModelProvider.Factoryインターフェースを使用してViewModelオブジェクトを作成する方法。
学習内容
LiveDataオブジェクトが有用な理由。ViewModelに保存されているデータにLiveDataを追加する方法。MutableLiveDataを使用するタイミングと方法。LiveData.での変更を監視するオブザーバー メソッドを追加する方法- バッキング プロパティを使用して
LiveDataをカプセル化する方法。 - UI コントローラと対応する
ViewModelの間で通信する方法。
演習内容
- GuessTheWord アプリで、単語とスコアに
LiveDataを使用します。 - 単語やスコアが変更されたときに通知を受け取るオブザーバーを追加します。
- 変更された値を表示するテキスト ビューを更新します。
LiveDataオブザーバー パターンを使用して、ゲーム終了イベントを追加します。- [Play Again] ボタンを実装します。
レッスン 5 の Codelab では、スターター コードから GuessTheWord アプリを開発します。GuessTheWord は、2 人のプレーヤーが最高スコアを目指して協力する、2 プレーヤー ジェスチャー ゲームです。
最初のプレーヤーはアプリの単語を見て、2 番目のプレーヤーに単語を見せないようにしながら、各単語を順番に演じます。2 人目のプレーヤーが単語を当てようとします。
ゲームをプレイするには、最初のプレーヤーがデバイスでアプリを開き、下のスクリーンショットに示すように、「ギター」などの単語を表示します。
最初のプレーヤーは、単語自体を言わないように注意しながら、単語を演じます。
- 2 人目のプレーヤーが単語を正しく当てると、1 人目のプレーヤーが [Got It] ボタンを押します。これにより、カウントが 1 つ増え、次の単語が表示されます。
- 2 人目のプレーヤーが単語を当てられない場合、1 人目のプレーヤーが [スキップ] ボタンを押します。これにより、カウントが 1 減り、次の単語にスキップします。
- ゲームを終了するには、[End Game] ボタンを押します。(この機能は、シリーズの最初の Codelab のスターター コードには含まれていません)。
この Codelab では、ユーザーがアプリ内のすべての単語を使い切ったときにゲームを終了するイベントを追加して、GuessTheWord アプリを改善します。また、スコア フラグメントに [もう一度プレイ ] ボタンを追加して、ユーザーがゲームをもう一度プレイできるようにします。
タイトル画面 |
ゲーム画面 |
スコア画面 |
このタスクでは、この Codelab のスターター コードを見つけて実行します。前の Codelab で作成した GuessTheWord アプリをスターター コードとして使用することも、スターター アプリをダウンロードすることもできます。
- (省略可)前の Codelab のコードを使用しない場合は、この Codelab のスターター コードをダウンロードします。コードの ZIP ファイルを展開し、プロジェクトを Android Studio で開きます。
- アプリを実行して、ゲームをプレイします。
- [Skip] ボタンをタップすると、次の単語が表示され、スコアが 1 減ります。[Got It] ボタンをタップすると、次の単語が表示され、スコアが 1 増えます。[ゲームを終了] ボタンをクリックすると、ゲームが終了します。
LiveData は、ライフサイクル対応の監視可能なデータホルダー クラスです。たとえば、GuessTheWord アプリの現在のスコアを LiveData でラップできます。この Codelab では、LiveData のいくつかの特性について学びます。
LiveDataは監視可能です。つまり、LiveDataオブジェクトに保持されているデータが変更されるとオブザーバーに通知されます。LiveDataにはデータが保持されます。LiveDataはあらゆる種類のデータに使用できるラッパーです。LiveDataはライフサイクル対応です。つまり、STARTEDやRESUMEDなどのアクティブなライフサイクルの状態にあるオブザーバーのみを更新します。
このタスクでは、GameViewModel にある現在のスコアと現在の単語のデータを LiveData に変換することによって、あらゆるデータ型を 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チェックを追加します。次に、scoreでminus()関数を呼び出します。この関数はnull-safety で減算を行います。
fun onSkip() {
if (!wordList.isEmpty()) {
score.value = (score.value)?.minus(1)
}
nextWord()
}- 同様に
onCorrect()メソッドを更新します。score変数にnullチェックを追加し、plus()関数を使用します。
fun onCorrect() {
if (!wordList.isEmpty()) {
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()
}GameFragmentの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)
}- コードにエラーがないことを確認します。アプリをコンパイルして実行します。アプリの機能は以前と同じであるはずです。
このタスクは、スコアと単語のデータを LiveData オブジェクトに変換した前のタスクと密接に関連しています。このタスクでは、Observer オブジェクトをこれらの LiveData オブジェクトに接続します。
onCreateView()メソッド内のGameFragment,で、現在のスコアviewModel.scoreのLiveDataオブジェクトにObserverオブジェクトをアタッチします。observe()メソッドを使用し、viewModelの初期化後にコードを配置します。ラムダ式を使用してコードを簡素化します。(ラムダ式は、宣言されない匿名関数であり、式としてその場で渡されます)。
viewModel.score.observe(this, Observer { newScore ->
})Observer への参照を解決します。これを行うには、Observer をクリックして Alt+Enter(Mac の場合は Option+Enter)を押し、androidx.lifecycle.Observer をインポートします。
- 作成したオブザーバーは、監視対象の
LiveDataオブジェクトに保持されているデータが変更されるとイベントを受け取ります。オブザーバー内で、スコアTextViewを新しいスコアで更新します。
/** Setting up LiveData observation relationship **/
viewModel.score.observe(this, Observer { newScore ->
binding.scoreText.text = newScore.toString()
})Observerオブジェクトを現在の単語のLiveDataオブジェクトにアタッチします。Observerオブジェクトを現在のスコアに関連付けたときと同じ方法で行います。
/** Setting up LiveData observation relationship **/
viewModel.word.observe(this, Observer { newWord ->
binding.wordText.text = newWord
})score または word の値が変更されると、画面に表示される score または word が自動的に更新されます。
GameFragmentで、メソッドupdateWordText()とupdateScoreText()、およびそれらへの参照をすべて削除します。テキスト ビューはLiveDataオブザーバー メソッドによって更新されるため、これらは不要になりました。- アプリを実行します。ゲームアプリは、前とまったく同じように動作しますが、
LiveDataとLiveDataオブザーバーを使用するようになります。
カプセル化により、オブジェクトの一部フィールドへの直接アクセスを制限できます。オブジェクトをカプセル化する場合は、非公開の内部フィールドを変更するためのパブリック メソッドを公開します。カプセル化することで、内部フィールドに対する他のクラスからの操作を制御できます。
現在のコードでは、外部クラスは value プロパティ(たとえば viewModel.score.value)を使用して score 変数と word 変数を変更できます。この Codelab で開発するアプリでは問題にならないかもしれませんが、本番環境のアプリでは、ViewModel オブジェクト内のデータを制御する必要があります。
アプリ内のデータを編集できるのは ViewModel のみです。ただし、UI コントローラはデータを読み取る必要があるため、データ フィールドを完全に非公開にすることはできません。アプリのデータをカプセル化するには、MutableLiveData オブジェクトと LiveData オブジェクトの両方を使用します。
MutableLiveData 対 LiveData:
MutableLiveDataオブジェクト内のデータは、名前が示すように変更できます。ViewModel内ではデータを編集できるように、MutableLiveDataを使用します。LiveDataオブジェクト内のデータは読み取ることができますが、変更することはできません。ViewModelの外部からは、データを読み取り可能にし、変更は不可能にする必要があるため、データをLiveDataとして公開する必要があります。
この戦略を実行するには、Kotlin のバッキング プロパティを使用します。バッキング プロパティを使用すると、そのオブジェクト自体ではなくゲッターから返すことができます。このタスクでは、GuessTheWord アプリの score オブジェクトと word オブジェクトのバッキング プロパティを実装します。
バッキング プロパティをスコアと単語に追加する
GameViewModelで、現在のscoreオブジェクトをprivateにします。- バッキング プロパティで使用されている命名規則に従って、
scoreを_scoreに変更します。_scoreプロパティは、内部で使用されるゲームスコアの可変バージョンになりました。 scoreという名前のLiveData型のパブリック バージョンを作成します。
// The current score
private val _score = MutableLiveData<Int>()
val score: LiveData<Int>- 初期化エラーが表示される。このエラーは、
GameFragment内でscoreがLiveData参照であり、scoreがセッターにアクセスできなくなったために発生します。Kotlin のゲッターとセッターについて詳しくは、ゲッターとセッターをご覧ください。
エラーを解決するには、GameViewModelのscoreオブジェクトのget()メソッドをオーバーライドし、バッキング プロパティ_scoreを返します。
val score: LiveData<Int>
get() = _scoreGameViewModelで、scoreの参照を内部の変更可能なバージョンである_scoreに変更します。
init {
...
_score.value = 0
...
}
...
fun onSkip() {
if (!wordList.isEmpty()) {
_score.value = (score.value)?.minus(1)
}
...
}
fun onCorrect() {
if (!wordList.isEmpty()) {
_score.value = (score.value)?.plus(1)
}
...
}scoreオブジェクトの場合と同様に、wordオブジェクトの名前を_wordに変更し、バッキング プロパティを追加します。
// The current word
private val _word = MutableLiveData<String>()
val word: LiveData<String>
get() = _word
...
init {
_word.value = ""
...
}
...
private fun nextWord() {
if (!wordList.isEmpty()) {
//Select and remove a word from the list
_word.value = wordList.removeAt(0)
}
}LiveData オブジェクト word と score をカプセル化しました。
現在のアプリでは、ユーザーが [End Game] ボタンをタップすると、スコア画面に移動します。また、プレーヤーがすべての単語を完了したら、アプリがスコア画面に移動するようにします。プレーヤーが最後の単語を言い終えたら、ユーザーがボタンをタップしなくてもゲームが自動的に終了するようにします。
この機能を実装するには、すべての単語が表示されたときに ViewModel からフラグメントにトリガーされて通知されるイベントが必要です。これを行うには、LiveData オブザーバー パターンを使用してゲーム終了イベントをモデル化します。
オブザーバー パターン
オブザーバー パターンは、ソフトウェア設計パターンです。オブジェクト間の通信(オブザーバブル(観察の「対象」)とオブザーバー)を指定します。オブザーバブルは、状態の変化をオブザーバーに通知するオブジェクトです。

このアプリの LiveData の場合、オブザーバブル(サブジェクト)は LiveData オブジェクトであり、オブザーバーはフラグメントなどの UI コントローラのメソッドです。LiveData 内のデータが変更されるたびに、状態が変化します。LiveData クラスは、ViewModel からフラグメントへの通信において重要です。
ステップ 1: LiveData を使用してゲーム終了イベントを検出する
このタスクでは、LiveData オブザーバー パターンを使用してゲーム終了イベントをモデル化します。
GameViewModelで、_eventGameFinishというBooleanMutableLiveDataオブジェクトを作成します。このオブジェクトはゲーム終了イベントを保持します。_eventGameFinishオブジェクトを初期化した後、eventGameFinishという名前のバッキング プロパティを作成して初期化します。
// Event which triggers the end of the game
private val _eventGameFinish = MutableLiveData<Boolean>()
val eventGameFinish: LiveData<Boolean>
get() = _eventGameFinishGameViewModelにonGameFinish()メソッドを追加します。このメソッドで、ゲーム終了イベントeventGameFinishをtrueに設定します。
/** Method for the game completed event **/
fun onGameFinish() {
_eventGameFinish.value = true
}GameViewModelのnextWord()メソッド内で、単語リストが空の場合にゲームを終了します。
private fun nextWord() {
if (wordList.isEmpty()) {
onGameFinish()
} else {
//Select and remove a _word from the list
_word.value = wordList.removeAt(0)
}
}GameFragmentのonCreateView()内で、viewModelを初期化した後、eventGameFinishにオブザーバーをアタッチします。observe()メソッドを使用します。ラムダ関数内で、gameFinished()メソッドを呼び出します。
// Observer for the Game finished event
viewModel.eventGameFinish.observe(this, Observer<Boolean> { hasFinished ->
if (hasFinished) gameFinished()
})- アプリを実行し、ゲームをプレイして、すべての単語をプレイします。[ゲームを終了] をタップするまでゲーム フラグメントにとどまるのではなく、スコア画面に自動的に移動します。
単語リストが空になると、eventGameFinishが設定され、ゲーム フラグメントの関連するオブザーバー メソッドが呼び出され、アプリは画面フラグメントに移動します。 - 追加したコードによってライフサイクルの問題が発生しています。問題を把握するため、
GameFragmentクラスのgameFinished()メソッドでナビゲーション コードをコメントアウトします。メソッドにToastメッセージを保持するようにしてください。
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)
}
- アプリを実行し、ゲームをプレイして、すべての単語をプレイします。ゲーム画面の下部に「ゲームが終了しました」というトースト メッセージが短時間表示されます。これは想定される動作です。
デバイスまたはエミュレータを回転させます。トーストが再び表示されます。デバイスを数回回転させると、おそらく毎回トーストが表示されます。これはバグです。トーストはゲームが終了したときに 1 回だけ表示されるはずです。フラグメントが再作成されるたびにトーストが表示されるべきではありません。この問題は次のタスクで解決します。
|
|
ステップ 2: ゲーム終了イベントをリセットする
通常、LiveData はデータが変更された場合にのみオブザーバーに更新を配信します。オブザーバーは、非アクティブな状態からアクティブな状態に変わったときにも最新データを受け取りますが、これは例外的な動作です。
そのため、アプリでゲーム終了のトーストが繰り返しトリガーされます。画面の回転後にゲーム フラグメントが再作成されると、非アクティブ状態からアクティブ状態に移行します。フラグメント内のオブザーバーが既存の ViewModel に再接続され、現在のデータを受信します。gameFinished() メソッドが再度トリガーされ、トーストが表示されます。
このタスクでは、GameViewModel の eventGameFinish フラグをリセットして、この問題を修正し、トーストを 1 回だけ表示します。
GameViewModelで、ゲーム終了イベント_eventGameFinishをリセットするonGameFinishComplete()メソッドを追加します。
/** Method for the game completed event **/
fun onGameFinishComplete() {
_eventGameFinish.value = false
}GameFragmentのgameFinished()の最後で、viewModelオブジェクトのonGameFinishComplete()を呼び出します。(ナビゲーション コードはgameFinished()でコメントアウトしたままにしておきます)。
private fun gameFinished() {
...
viewModel.onGameFinishComplete()
}- アプリを実行して、ゲームをプレイします。すべての単語を確認してから、デバイスの画面の向きを変更します。トーストは 1 回だけ表示されます。
GameFragmentのgameFinished()メソッド内で、ナビゲーション コードのコメントを解除します。
Android Studio でコメントを解除するには、コメントアウトされている行を選択してControl+/(Mac の場合はCommand+/)を押します。
private fun gameFinished() {
Toast.makeText(activity, "Game has just finished", Toast.LENGTH_SHORT).show()
val action = GameFragmentDirections.actionGameToScore()
action.score = viewModel.score.value?:0
findNavController(this).navigate(action)
viewModel.onGameFinishComplete()
}Android Studio のプロンプトが表示された場合は、androidx.navigation.fragment.NavHostFragment.findNavController をインポートします。
- アプリを実行して、ゲームをプレイします。すべての単語を終えた後、アプリが自動的に最終スコア画面に移動することを確認します。
|
|
その調子です。アプリは LiveData を使用してゲーム終了イベントをトリガーし、GameViewModel から単語リストが空であることをゲーム フラグメントに伝えます。ゲーム フラグメントはスコア フラグメントに移動します。
このタスクでは、ScoreViewModel のスコアを LiveData オブジェクトに変更し、オブザーバーをアタッチします。このタスクは、GameViewModel に LiveData を追加したときに行った作業と似ています。
これらの変更は、アプリ内のすべてのデータが LiveData を使用するように、完全性を確保するために ScoreViewModel に行います。
ScoreViewModelで、score変数の型をMutableLiveDataに変更します。慣例に従って_scoreに名前を変更し、バッキング プロパティを追加します。
private val _score = MutableLiveData<Int>()
val score: LiveData<Int>
get() = _scoreScoreViewModelのinitブロック内で、_scoreを初期化します。initブロックのログは、必要に応じて削除またはそのままにできます。
init {
_score.value = finalScore
}ScoreFragmentのonCreateView()内で、viewModelを初期化した後、スコアLiveDataオブジェクトのオブザーバーをアタッチします。ラムダ式内で、スコア値をスコア テキストビューに設定します。ViewModelから、スコア値をテキストビューに直接割り当てるコードを削除します。
追加するコード:
// Add observer for score
viewModel.score.observe(this, Observer { newScore ->
binding.scoreText.text = newScore.toString()
})削除するコード:
binding.scoreText.text = viewModel.score.toString()Android Studio のプロンプトが表示されたら、androidx.lifecycle.Observer をインポートします。
- アプリを実行して、ゲームをプレイします。アプリは以前と同じように動作しますが、スコアの更新に
LiveDataとオブザーバーを使用するようになります。
このタスクでは、スコア画面に [Play Again] ボタンを追加し、LiveData イベントを使用してクリック リスナーを実装します。ボタンは、スコア画面からゲーム画面に移動するイベントをトリガーします。
アプリのスターター コードには [もう一度プレイ] ボタンが含まれていますが、このボタンは非表示になっています。
res/layout/score_fragment.xmlのplay_again_buttonボタンで、visibility属性の値をvisibleに変更します。
<Button
android:id="@+id/play_again_button"
...
android:visibility="visible"
/>ScoreViewModelで、_eventPlayAgainというBooleanを保持するLiveDataオブジェクトを追加します。このオブジェクトは、スコア画面からゲーム画面に移動するためにLiveDataイベントを保存するために使用されます。
private val _eventPlayAgain = MutableLiveData<Boolean>()
val eventPlayAgain: LiveData<Boolean>
get() = _eventPlayAgainScoreViewModelで、イベント_eventPlayAgainを設定およびリセットするメソッドを定義します。
fun onPlayAgain() {
_eventPlayAgain.value = true
}
fun onPlayAgainComplete() {
_eventPlayAgain.value = false
}ScoreFragmentで、eventPlayAgainのオブザーバーを追加します。コードをonCreateView()の末尾、returnステートメントの前に配置します。ラムダ式内で、ゲーム画面に戻り、eventPlayAgainをリセットします。
// Navigates back to game when button is pressed
viewModel.eventPlayAgain.observe(this, Observer { playAgain ->
if (playAgain) {
findNavController().navigate(ScoreFragmentDirections.actionRestart())
viewModel.onPlayAgainComplete()
}
})Android Studio のプロンプトが表示されたら、androidx.navigation.fragment.findNavController をインポートします。
ScoreFragmentのonCreateView()の中で、[PlayAgain] ボタンにクリック リスナーを追加し、viewModel.onPlayAgain()を呼び出します。
binding.playAgainButton.setOnClickListener { viewModel.onPlayAgain() }- アプリを実行して、ゲームをプレイします。ゲームが終了すると、スコア画面に最終スコアと [Play Again](もう一度プレイ)ボタンが表示されます。[PlayAgain] ボタンをタップすると、アプリがゲーム画面に移動し、ゲームを再度プレイできます。

よかったですね!アプリのアーキテクチャを変更して ViewModel で LiveData オブジェクトを使用し、オブザーバーを LiveData オブジェクトにアタッチしました。LiveData は、LiveData が保持する値が変更されるとオブザーバー オブジェクトに通知します。
Android Studio プロジェクト: GuessTheWord
LiveData
LiveDataは、ライフサイクル対応の監視可能なデータホルダー クラスであり、Android アーキテクチャ コンポーネントの 1 つです。LiveDataを使用すると、データが更新されたときに UI が自動的に更新されるようにできます。LiveDataは監視可能です。つまり、LiveDataオブジェクトに保持されているデータが変更されると、アクティビティやフラグメントなどのオブザーバーに通知されます。LiveDataにはデータが保持されます。これは、あらゆる種類のデータに使用できるラッパーです。LiveDataはライフサイクル対応です。つまり、STARTEDやRESUMEDなどのアクティブなライフサイクルの状態にあるオブザーバーのみを更新します。
LiveData を追加するには
ViewModelのデータ変数の型をLiveDataまたはMutableLiveDataに変更します。
MutableLiveData は、値を変更できる LiveData オブジェクトです。MutableLiveData は汎用のクラスであるため、保持するデータの種類を指定する必要があります。
LiveDataが保持するデータの値を変更するには、LiveData変数でsetValue()メソッドを使用します。
LiveData をカプセル化するには
ViewModel内のLiveDataは編集可能である必要があります。ViewModelの外部では、LiveDataは読み取り可能である必要があります。これは、Kotlin のバッキング プロパティを使用して実装できます。- Kotlin のバッキング プロパティを使用すると、そのオブジェクト自体ではなくゲッターから返すことができます。
LiveDataをカプセル化するには、ViewModel内でprivateMutableLiveDataを使用し、ViewModelの外でLiveDataバッキング プロパティを返します。
Observable LiveData
LiveDataはオブザーバー パターンに従います。「オブザーバブル」はLiveDataオブジェクトで、オブザーバーはフラグメントなどの UI コントローラのメソッドです。LiveData内でラップされたデータが変更されるたびに、UI コントローラのオブザーバー メソッドに通知が送信されます。LiveDataをオブザーバブルにするには、observe()メソッドを使用して、オブザーバー(アクティビティやフラグメントなど)のLiveData参照にオブザーバー オブジェクトをアタッチします。- この
LiveDataオブザーバー パターンを使用して、ViewModelから UI コントローラに通信できます。
Udacity コース:
Android デベロッパー ドキュメント:
その他:
- Kotlin のバッキング プロパティ
このセクションでは、インストラクター主導のコースの一環として、この Codelab に取り組んでいる生徒向けに考えられる宿題をいくつか示します。インストラクターは、以下のようなことを行えます。
- 必要に応じて宿題を与える
- 宿題の提出方法を生徒に伝える
- 宿題を採点する
インストラクターは、これらの提案を必要なだけ使用し、必要に応じて他の宿題も自由に与えることができます。
この Codelab に独力で取り組む場合は、これらの宿題を自由に使用して知識をテストしてください。
以下の質問に回答してください
問題 1
ViewModel に格納された LiveData をカプセル化して、外部オブジェクトがデータを更新せずに読み取れるようにするにはどうすればよいですか。
ViewModelオブジェクト内で、データのデータ型をprivateLiveDataに変更する。バッキング プロパティを使用して、MutableLiveData型の読み取り専用データを公開する。ViewModelオブジェクト内で、データのデータ型をprivateMutableLiveDataに変更する。バッキング プロパティを使用して、LiveData型の読み取り専用データを公開する。- UI コントローラ内で、データのデータ型を
privateMutableLiveDataに変更する。バッキング プロパティを使用して、LiveData型の読み取り専用データを公開する。 ViewModelオブジェクト内で、データのデータ型をLiveDataに変更する。バッキング プロパティを使用して、LiveData型の読み取り専用データを公開する。
問題 2
LiveData が UI コントローラ(フラグメントなど)を更新するのは、UI コントローラが次のうちどの状態にある場合ですか?
- 再開
- バックグラウンド
- 一時停止
- 停止
問題 3
LiveData オブザーバー パターンで、監視可能なアイテム(監視対象)は何ですか?
- オブザーバー メソッド
LiveDataオブジェクト内のデータ- UI コントローラ
ViewModelオブジェクト
次のレッスンに進む:
このコースの他の Codelab へのリンクについては、Android Kotlin の基礎の Codelab のランディング ページをご覧ください。




