この Codelab は、Android Kotlin の基礎コースの一部です。Codelab を順番に進めていくと、このコースを最大限に活用できます。すべてのコース Codelab は Android Kotlin の基礎 Codelab ランディング ページに掲載されています。
はじめに
前の Codelab では、GessTheWord アプリで ViewModel
を使用して、デバイスの構成変更後もアプリのデータが保持されるようにしました。この Codelab では、LiveData
を ViewModel
クラスのデータと統合する方法を学びます。Android アーキテクチャ コンポーネントの 1 つである LiveData
を使用すると、基盤となるデータベースが変更されたときにビューに通知するデータ オブジェクトを作成できます。
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 人構成のキャラクター スタイル ゲームで、プレーヤーが協力して最高スコアを獲得します。
1 人目のプレーヤーはアプリで単語を確認し、2 人目のプレーヤーに単語を表示しないように順番に実行します。2 人目のプレーヤーがその単語を推測します。
ゲームをプレイするには、最初のプレーヤーがデバイスでアプリを開き、以下のスクリーンショットに示すように「ギター」などの単語が表示されます。
1 人目のプレーヤーが単語を実際に操作し、単語そのものを言わないように注意します。
- 2 人目のプレーヤーが単語を正しく推測したら、[OK] ボタンを押すと、カウントが 1 つ増えて次の単語が表示されます。
- 2 人目のプレーヤーが単語を推測できない場合は、[スキップ] ボタンを押すと、カウントが 1 つ減って次の単語に進みます。
- ゲームを終了するには、[ゲームを終了] ボタンを押します。(この機能は、シリーズの最初の Codelab のスターター コードにはありません)。
この Codelab では、ユーザーがアプリのすべての単語間を移動したときにゲームを終了するイベントを追加して、GuesTheWord アプリを改善します。また、スコアフラグメントに [Play Again] ボタンを追加して、ユーザーがゲームをもう一度プレイできるようにします。
タイトル画面 |
ゲーム画面 |
スコア画面 |
このタスクでは、この Codelab のスターター コードを見つけて実行します。前の Codelab で作成した GuessTheWord アプリをスターター コードとして使用することも、スターター アプリをダウンロードすることもできます。
- (省略可)前の Codelab のコードを使用していない場合は、この Codelab のスターター コードをダウンロードします。コードを解凍し、Android Studio でプロジェクトを開きます。
- アプリを実行して、ゲームをプレイします。
- [Skip] ボタンでは次の単語を表示し、スコアを 1 つ減らします。[Got It] ボタンでは次の単語を表示してスコアを 1 つ増やします。[ゲームを終了] ボタンをクリックするとゲームが終了します。
LiveData
はライフサイクル対応の監視可能なデータホルダー クラスです。たとえば、GessTheWord アプリで現在のスコアに 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
の安全性を確保した状態で減算が行われます。
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
オブジェクトに変換した前のタスクと密接に関連しています。このタスクでは、これらの LiveData
オブジェクトに Observer
オブジェクトをアタッチします。
GameFragment,
のonCreateView()
メソッドで、現在のスコア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()
})
- 現在の単語
LiveData
オブジェクトにObserver
オブジェクトをアタッチします。このメソッドは、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 バッキング プロパティを使用します。バッキング プロパティを使用すると、そのオブジェクト自体ではなくゲッターから返すことができます。このタスクでは、GuesTheWord アプリに 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() = _score
GameViewModel
で、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
がカプセル化されました。
ユーザーが [ゲームを終了] ボタンをタップすると、現在のアプリがスコア画面に移動します。また、プレーヤーがすべての単語を切り替えたときに、スコア画面に移動するようにします。プレーヤーが最後の単語でゲームを終えたら、ユーザーがボタンをタップしなくてもゲームを自動的に終了できるようにします。
この機能を実装するには、すべての単語が表示されたときにイベントをトリガーし、ViewModel
からフラグメントに伝える必要があります。これを行うには、LiveData
オブザーバー パターンを使用して、ゲーム終了イベントをモデル化します。
オブザーバー パターン
オブザーバー パターンは、ソフトウェア設計パターンです。オブジェクト間の通信を指定する。監視可能(観測の「対象」)とオブザーバーです。オブザーバブルは、オブザーバーの状態の変化をオブザーバーに通知するオブジェクトです。
このアプリの LiveData
の場合、オブザーバブル(サブジェクト)は LiveData
オブジェクトで、オブザーバーはフラグメントなどの UI コントローラのメソッドです。状態の変化は、LiveData
内にラップされたデータが変更されるたびに発生します。LiveData
クラスは、ViewModel
からフラグメントへの通信において非常に重要です。
ステップ 1: LiveData を使用して、ゲーム終了イベントを検出する
このタスクでは、LiveData
オブザーバー パターンを使用して、ゲーム終了イベントをモデル化します。
GameViewModel
で、_eventGameFinish
というBoolean
MutableLiveData
オブジェクトを作成します。このオブジェクトは、ゲーム終了イベントを保持します。_eventGameFinish
オブジェクトを初期化したら、eventGameFinish
というバッキング プロパティを作成して初期化します。
// Event which triggers the end of the game
private val _eventGameFinish = MutableLiveData<Boolean>()
val eventGameFinish: LiveData<Boolean>
get() = _eventGameFinish
GameViewModel
に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
オブジェクトに変更し、オブザーバーをアタッチします。このタスクは、LiveData
を GameViewModel
に追加したときのタスクと似ています。
完全性のためにこれらの変更を ScoreViewModel
に変更し、アプリのすべてのデータで LiveData
を使用できるようにします。
ScoreViewModel
で、score
変数タイプをMutableLiveData
に変更します。慣例として、名前を_score
に変更し、バッキング プロパティを追加します。
private val _score = MutableLiveData<Int>()
val score: LiveData<Int>
get() = _score
ScoreViewModel
の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
イベントを使用してクリック リスナーを実装します。このボタンは、スコア画面からゲーム画面に移動するイベントをトリガーします。
アプリのスターター コードには [Play Again] ボタンがありますが、ボタンは非表示になっています。
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() = _eventPlayAgain
ScoreViewModel
で、イベント_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
内でprivate
MutableLiveData
を使用し、ViewModel
の外部でLiveData
バッキング プロパティを返します。
オブザーバブル LiveData
LiveData
はオブザーバー パターンに従います。「オブザーバブル」はLiveData
オブジェクトで、オブザーバーはフラグメントなどの UI コントローラのメソッドです。LiveData
内にラップされたデータが変更されるたびに、UI コントローラのオブザーバー メソッドに通知されます。LiveData
をオブザーバブルにするには、observe()
メソッドを使用してオブザーバー(アクティビティやフラグメントなど)のLiveData
参照にオブザーバー オブジェクトを追加します。- この
LiveData
オブザーバー パターンを使用すると、ViewModel
から UI コントローラと通信できます。
Udacity コース:
Android デベロッパー ドキュメント:
その他:
- Kotlin のバッキング プロパティ
このセクションでは、インストラクターが主導するコースの一環として、この Codelab に取り組む生徒の課題について説明します。教師は以下のことを行えます。
- 必要に応じて課題を割り当てます。
- 宿題の提出方法を生徒に伝える。
- 宿題を採点します。
教師はこれらの提案を少しだけ使うことができます。また、他の課題は自由に割り当ててください。
この Codelab にご自分で取り組む場合は、これらの課題を使用して知識をテストしてください。
次の質問に答えてください。
問題 1
ViewModel
に保存されている LiveData
をカプセル化して、外部オブジェクトがデータを更新せずに読み取るにはどうすればよいでしょうか。
ViewModel
オブジェクト内で、データのデータ型をprivate
LiveData
に変更します。バッキング プロパティを使用して、MutableLiveData
型の読み取り専用データを公開する。ViewModel
オブジェクト内で、データのデータ型をprivate
MutableLiveData
に変更します。バッキング プロパティを使用して、LiveData
型の読み取り専用データを公開する。- UI コントローラ内で、データのデータ型を
private
MutableLiveData
に変更します。バッキング プロパティを使用して、LiveData
型の読み取り専用データを公開する。 ViewModel
オブジェクト内で、データのデータ型をLiveData
に変更します。バッキング プロパティを使用して、LiveData
型の読み取り専用データを公開する。
質問 2
LiveData
が UI コントローラ(フラグメントなど)を更新する場合、UI コントローラが次のどの状態にあるか。
- 再開
- バックグラウンド
- 一時停止
- 停止
問題 3
LiveData
オブザーバー パターンで、監視可能なアイテム(監視対象のアイテム)は何ですか?
- オブザーバー メソッド
LiveData
オブジェクト内のデータ- UI コントローラ
ViewModel
オブジェクト
次のレッスンを開始する:
このコースの他の Codelab へのリンクについては、Android Kotlin の基礎 Codelab ランディング ページをご覧ください。