Android Kotlin 基礎知識 05.2:LiveData 和 LiveData 觀測器

這個程式碼研究室是 Android Kotlin 基礎知識課程的一部分。如果您按部就班完成程式碼研究室,就能充分體驗到本課程的價值。所有課程程式碼研究室都列在 Android Kotlin 基礎知識程式碼研究室到達網頁。

簡介

在先前的程式碼研究室中,您已在 GuessTheWord 應用程式中使用 ViewModel,確保應用程式資料在裝置設定變更後仍然有效。在本程式碼研究室中,您將瞭解如何整合 LiveData 與 ViewModel 類別中的資料。LiveData 是 Android 架構元件之一,可讓您建構資料物件,在基礎資料庫變更時通知檢視區塊。

如要使用 LiveData 類別,請設定「觀察程式」(例如活動或片段),觀察應用程式資料的變更。LiveData 具備生命週期感知功能,因此只會更新處於有效生命週期狀態的應用程式元件觀察器。

必備知識

  • 如何使用 Kotlin 建構基本 Android 應用程式。
  • 如何瀏覽應用程式的目的地。
  • 活動和片段生命週期。
  • 如何在應用程式中使用 ViewModel 物件。
  • 如何使用 ViewModelProvider.Factory 介面建立 ViewModel 物件。

課程內容

  • LiveData 物件的實用之處。
  • 如何將 LiveData 新增至儲存在 ViewModel 中的資料。
  • 使用 MutableLiveData 的時機和方式。
  • 如何新增觀察器方法以觀察 LiveData. 中的變化。
  • 如何使用幕後屬性封裝 LiveData。
  • 如何讓 UI 控制器與對應的 ViewModel 進行通訊。

學習內容

  • 在 GuessTheWord 應用程式中,針對字詞和分數使用 LiveData。
  • 新增觀察器,在字詞或分數變更時接收通知。
  • 更新顯示變更值的文字檢視區塊。
  • 使用 LiveData 觀察器模式新增遊戲完成事件。
  • 實作「Play Again」按鈕。

在第 5 課的程式碼研究室中,您將從範例程式碼開始開發 GuessTheWord 應用程式。GuessTheWord 是雙人比手畫腳遊戲,玩家要彼此合作,盡可能獲得最高分。

第一位玩家看著應用程式中的字詞,輪流表演每個字詞,但要確保第二位玩家看不到字詞。第二位玩家嘗試猜測字詞。

如要開始遊戲,第一位玩家要在裝置上開啟應用程式,並看到一個字詞,例如「吉他」,如下方螢幕截圖所示。

第一位玩家要表演這個字詞,但不能說出該字詞。

  • 第二位玩家猜對字詞後,第一位玩家會按下「Got It」按鈕,計數會增加一,並顯示下一個字詞。
  • 如果第二位玩家猜不出單字,第一位玩家可以按下「略過」按鈕,這樣一來,計數就會減少 1,並跳到下一個單字。
  • 如要結束遊戲,請按下「結束遊戲」按鈕。(這項功能不包含在系列第一個程式碼研究室的範例程式碼中)。

在本程式碼研究室中,您要改善 GuessTheWord 應用程式,加入一個事件,在使用者瀏覽應用程式中的所有字詞後結束遊戲。您也會在分數片段中加入「Play Again」 按鈕,讓使用者可以再次玩遊戲。

標題畫面

遊戲畫面

分數畫面

在這項工作中,您將找出並執行本程式碼研究室的範例程式碼。您可以使用先前程式碼研究室中建構的 GuessTheWord 應用程式做為範例程式碼,也可以下載範例應用程式。

  1. (選用) 如果您未使用上一個程式碼研究室的程式碼,請下載本程式碼研究室的範例程式碼。解壓縮程式碼,並在 Android Studio 中開啟專案。
  2. 執行應用程式並玩遊戲。
  3. 請注意,「略過」按鈕會顯示下一個字詞,並將分數減少 1 分;「答對了」按鈕會顯示下一個字詞,並將分數增加 1 分。結束遊戲按鈕會結束遊戲。

LiveData 是可觀察的資料容器類別,可感知生命週期。舉例來說,您可以在 GuessTheWord 應用程式中,將 LiveData 包裝在目前的分數周圍。在本程式碼研究室中,您將瞭解 LiveData 的幾項特徵:

  • LiveData 可觀察,這表示當 LiveData 物件保存的資料變更時,觀察器會接收通知。
  • LiveData 可保存資料;LiveData 包裝函式可與任何資料搭配使用
  • LiveData 具備生命週期感知功能,代表其只會更新處於有效生命週期狀態 (例如 STARTED 或 RESUMED) 的觀察器。

在這項工作中,您會學習如何將 GameViewModel 中的目前分數和目前字詞資料轉換為 LiveData,以將任何資料型別包裝成 LiveData 物件。在後續工作中,您會將觀察器新增至此類 LiveData 物件,並瞭解如何觀察 LiveData。

步驟 1:變更分數和字詞,改用 LiveData

  1. 在 screens/game 套件下,開啟 GameViewModel 檔案。
  2. 將變數 score 和 word 的類型變更為 MutableLiveData。

    MutableLiveData 是LiveData,其值可以變更。MutableLiveData 屬於一般類別,因此您需要指定其保存的資料類型。
// The current word
val word = MutableLiveData<String>()
// The current score
val score = MutableLiveData<Int>()
  1. 在 GameViewModel 中,於 init 區塊內初始化 score 和 word。如要變更 LiveData 變數的值,請對該變數使用 setValue() 方法。在 Kotlin 中,您可以使用 value 屬性呼叫 setValue()。
init {

   word.value = ""
   score.value = 0
  ...
}

步驟 2:更新 LiveData 物件參照

score 和 word 變數現在屬於 LiveData 類型。在這個步驟中,您會使用 value 屬性,變更對這些變數的參照。

  1. 在 GameViewModel 的 onSkip() 方法中,將 score 變更為 score.value。請注意,錯誤訊息指出 score 可能為 null。您將在下一個步驟修正此錯誤。
  2. 如要解決這項錯誤,請在 onSkip() 的 score.value 中新增 null 檢查。然後在 score 上呼叫 minus() 函式,以執行 null 安全減法。
fun onSkip() {
   if (!wordList.isEmpty()) {
       score.value = (score.value)?.minus(1)
   }
   nextWord()
}
  1. 以相同方式更新 onCorrect() 方法:在 score 變數中新增 null 檢查,並使用 plus() 函式。
fun onCorrect() {
   if (!wordList.isEmpty()) {
       score.value = (score.value)?.plus(1)
   }
   nextWord()
}
  1. 在 GameViewModel 的 nextWord() 方法中,將 word 參照變更為 word.value。
private fun nextWord() {
   if (!wordList.isEmpty()) {
       //Select and remove a word from the list
       word.value = wordList.removeAt(0)
   }
}
  1. 在 GameFragment 的 updateWordText() 方法中,將 viewModel.word 的參照變更為 viewModel.word.value.
/** Methods for updating the UI **/
private fun updateWordText() {
   binding.wordText.text = viewModel.word.value
}
  1. 在 GameFragment 的 updateScoreText() 方法中,將 viewModel.score 的參照變更為 viewModel.score.value.
private fun updateScoreText() {
   binding.scoreText.text = viewModel.score.value.toString()
}
  1. 在 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)
}
  1. 請確認程式碼中沒有錯誤。編譯並執行應用程式。應用程式的功能應與先前相同。

這項工作與前一個工作密切相關,您在前一個工作中將分數和字詞資料轉換為 LiveData 物件。在這項工作中,您要將 Observer 物件附加至這些 LiveData 物件。

  1. 在 GameFragment, 的 onCreateView() 方法中,將 Observer 物件附加至目前分數的 LiveData 物件 viewModel.score。使用 observe() 方法,並將程式碼放在 viewModel 初始化之後。使用 lambda 運算式簡化程式碼。(Lambda 運算式是未宣告的匿名函式,但會立即以運算式的形式傳遞。)
viewModel.score.observe(this, Observer { newScore ->
})

解決對 Observer 的參照。如要匯入 androidx.lifecycle.Observer,請點選 Observer,按下 Alt+Enter 鍵 (Mac 上為 Option+Enter 鍵)。

  1. 當觀察的 LiveData 物件保存的資料變更時,您剛建立的觀察器會收到事件。在觀察器內,使用新分數更新分數 TextView。
/** Setting up LiveData observation relationship **/
viewModel.score.observe(this, Observer { newScore ->
   binding.scoreText.text = newScore.toString()
})
  1. 將 Observer 物件附加至目前的字詞 LiveData 物件。方法與將 Observer 物件附加至目前分數相同。
/** Setting up LiveData observation relationship **/
viewModel.word.observe(this, Observer { newWord ->
   binding.wordText.text = newWord
})

當 score 或 word 的值變更時,畫面上顯示的 score 或 word 現在會自動更新。

  1. 在 GameFragment 中,刪除 updateWordText() 和 updateScoreText() 方法,以及所有對這些方法的參照。您已無需使用這些觀察器,因為文字檢視畫面會由 LiveData 觀察器方法更新。
  2. 執行應用程式。您的遊戲應用程式應可照常運作,但現在會使用 LiveData 和 LiveData 觀察器。

封裝是限制直接存取部分物件欄位的方式。封裝物件時,您將利用一組公開方法修改私人內部欄位。運用封裝,您可以控管其他類別操控這些內部欄位的方式。

在目前的程式碼中,任何外部類別都可以使用 value 屬性修改 score 和 word 變數,例如使用 viewModel.score.value。在本程式碼研究室中開發的應用程式可能不重要,但在正式版應用程式中,您會想控管 ViewModel 物件中的資料。

只有 ViewModel 才能編輯應用程式中的資料。不過,UI 控制器需要讀取資料,因此資料欄位無法完全私密。如要封裝應用程式的資料,請同時使用 MutableLiveData 和 LiveData 物件。

MutableLiveData與LiveData的比較:

  • 顧名思義,MutableLiveData 物件中的資料可以變更。ViewModel 內的資料應可編輯,因此會使用 MutableLiveData。
  • 您可以讀取 LiveData 物件中的資料,但無法變更。在 ViewModel 外部,資料應可供讀取,但無法編輯,因此資料應以 LiveData 的形式呈現。

如要執行這項策略,請使用 Kotlin 幕後屬性。幕後屬性可讓您從 getter 傳回確切物件以外的項目。在這項工作中,您要在「猜單字」應用程式中,為 score 和 word 物件實作支援屬性。

為分數和字詞新增幕後屬性

  1. 在 GameViewModel 中,將目前的 score 物件設為 private。
  2. 如要遵循幕後屬性使用的命名慣例,請將 score 變更為 _score。_score 屬性現在是遊戲分數的可變動版本,供內部使用。
  3. 建立 LiveData 類型的公開版本,並命名為 score。
// The current score
private val _score = MutableLiveData<Int>()
val score: LiveData<Int>
  1. 您看到初始化錯誤。發生這項錯誤的原因是 GameFragment 內部的 score 是 LiveData 參照,而 score 無法再存取其設定器。如要進一步瞭解 Kotlin 中的 getter 和 setter,請參閱「Getter 和 Setter」。

    如要解決錯誤,請在 GameViewModel 中覆寫 score 物件的 get() 方法,並傳回支援屬性 _score。
val score: LiveData<Int>
   get() = _score
  1. 在 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)
   }
   ...
}
  1. 將 word 物件重新命名為 _word,並為其新增幕後屬性,就像您對 score 物件所做的一樣。
// 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 觀察器模式,為遊戲結束事件建立模型。

  1. 在 GameViewModel 中,建立名為 _eventGameFinish 的 Boolean MutableLiveData 物件。這個物件會保存遊戲結束事件。
  2. 初始化 _eventGameFinish 物件後,請建立並初始化名為 eventGameFinish 的支援屬性。
// Event which triggers the end of the game
private val _eventGameFinish = MutableLiveData<Boolean>()
val eventGameFinish: LiveData<Boolean>
   get() = _eventGameFinish
  1. 在 GameViewModel 中新增 onGameFinish() 方法。在方法中,將遊戲完成事件 eventGameFinish 設為 true。
/** Method for the game completed event **/
fun onGameFinish() {
   _eventGameFinish.value = true
}
  1. 在 GameViewModel 的 nextWord() 方法中,如果字詞清單為空白,請結束遊戲。
private fun nextWord() {
   if (wordList.isEmpty()) {
       onGameFinish()
   } else {
       //Select and remove a _word from the list
       _word.value = wordList.removeAt(0)
   }
}
  1. 在 GameFragment 的 onCreateView() 中,初始化 viewModel 後,將觀察器附加至 eventGameFinish。請使用 observe() 方法。在 lambda 函式中呼叫 gameFinished() 方法。
// Observer for the Game finished event
viewModel.eventGameFinish.observe(this, Observer<Boolean> { hasFinished ->
   if (hasFinished) gameFinished()
})
  1. 執行應用程式,使用所有字詞進行遊戲。應用程式會自動前往分數畫面,而不是停留在遊戲片段,直到你輕觸「結束遊戲」為止。

    字詞清單清空後,系統會設定 eventGameFinish,並呼叫遊戲片段中相關聯的觀察器方法,然後應用程式會導覽至畫面片段。
  2. 您新增的程式碼導致生命週期問題。如要瞭解問題,請在 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 中,新增 onGameFinishComplete() 方法來重設遊戲完成事件 _eventGameFinish。
/** Method for the game completed event **/

fun onGameFinishComplete() {
   _eventGameFinish.value = false
}
  1. 在 GameFragment 中,於 gameFinished() 結尾,對 viewModel 物件呼叫 onGameFinishComplete()。(暫時將 gameFinished() 中的導覽程式碼加上註解)。
private fun gameFinished() {
   ...
   viewModel.onGameFinishComplete()
}
  1. 執行應用程式,然後進行遊戲。瀏覽所有單字,然後變更裝置的螢幕方向。系統只會顯示一次訊息。
  2. 在 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。

  1. 執行應用程式,然後進行遊戲。請確認應用程式會在您完成所有單字後,自動前往最終分數畫面。

太棒了!應用程式會使用 LiveData 觸發遊戲結束事件,從 GameViewModel 傳送訊息至遊戲片段,指出字詞清單為空白。遊戲片段接著會前往分數片段。

在這項工作中,您要將 ScoreViewModel 中的分數變更為 LiveData 物件,並附加觀察器。這項工作與您將 LiveData 新增至 GameViewModel 時的操作類似。

您會為了完整性而進行這些變更,確保應用程式中的所有資料都使用 LiveData。ScoreViewModel

  1. 在 ScoreViewModel 中,將 score 變數類型變更為 MutableLiveData。按照慣例將其重新命名為 _score,並新增幕後屬性。
private val _score = MutableLiveData<Int>()
val score: LiveData<Int>
   get() = _score
  1. 在 ScoreViewModel 的 init 區塊內,初始化 _score。您可以視需要移除或保留 init 區塊中的記錄。
init {
   _score.value = finalScore
}
  1. 在 ScoreFragment 的 onCreateView() 中,初始化 viewModel 後,附加分數 LiveData 物件的觀察器。在 lambda 運算式中,將分數值設為分數文字檢視區塊。從 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。

  1. 執行應用程式,然後進行遊戲。應用程式應可照常運作,但現在會使用 LiveData 和觀察器更新分數。

在這項工作中,您要在分數畫面上新增「Play Again」按鈕,並使用 LiveData 事件實作其點擊事件監聽器。這個按鈕會觸發事件,從分數畫面導覽至遊戲畫面。

應用程式的範例程式碼包含「Play Again」按鈕,但該按鈕已隱藏。

  1. 在 res/layout/score_fragment.xml 中,針對 play_again_button 按鈕,將 visibility 屬性的值變更為 visible。
<Button
   android:id="@+id/play_again_button"
...
   android:visibility="visible"
 />
  1. 在 ScoreViewModel 中,新增 LiveData 物件來保留名為 _eventPlayAgain 的 Boolean。這個物件用於儲存 LiveData 事件,以便從分數畫面導覽至遊戲畫面。
private val _eventPlayAgain = MutableLiveData<Boolean>()
val eventPlayAgain: LiveData<Boolean>
   get() = _eventPlayAgain
  1. 在 ScoreViewModel 中,定義設定及重設事件的方法 _eventPlayAgain。
fun onPlayAgain() {
   _eventPlayAgain.value = true
}
fun onPlayAgainComplete() {
   _eventPlayAgain.value = false
}
  1. 在 ScoreFragment 中,為 eventPlayAgain 新增觀察器。將程式碼放在 onCreateView() 的結尾,也就是 return 陳述式之前。在 lambda 運算式中,返回遊戲畫面並重設 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。

  1. 在 ScoreFragment 的 onCreateView() 內,將點按事件監聽器新增至「PlayAgain」按鈕,並呼叫 viewModel.onPlayAgain()。
binding.playAgainButton.setOnClickListener {  viewModel.onPlayAgain()  }
  1. 執行應用程式,然後進行遊戲。遊戲結束時,分數畫面會顯示最終分數和「Play Again」按鈕。輕觸「PlayAgain」PlayAgain按鈕,應用程式就會切換至遊戲畫面,讓您再次玩遊戲。

好極了!您已變更應用程式的架構,在 ViewModel 中使用 LiveData 物件,並將觀察器附加至 LiveData 物件。當 LiveData 保存的值變更時,LiveData 會通知觀察器物件。

Android Studio 專案:GuessTheWord

LiveData

  • LiveData 是可觀察的資料容器類別,可感知生命週期,屬於 Android 架構元件之一。
  • 您可以使用 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 幕後屬性可讓您從 getter 傳回確切物件以外的項目。
  • 如要封裝 LiveData,請在 ViewModel 中使用 private MutableLiveData,並在 ViewModel 外部傳回 LiveData 支援屬性。

可觀測的 LiveData

  • LiveData 遵循觀測器模式。「可觀察」的對象是 LiveData 物件,而觀察者是 UI 控制器 (例如片段) 中的方法。每當 LiveData 內包裝的資料變更時,UI 控制器中的觀察器方法就會收到通知。
  • 如要讓 LiveData 可供觀察,請使用 observe() 方法,將觀察器物件附加至觀察器 (例如活動和片段) 中的 LiveData 參照。
  • 這個 LiveData 觀察器模式可用於從 ViewModel 與 UI 控制器通訊。

Udacity 課程:

Android 開發人員說明文件:

其他:

本節列出的作業可由課程講師指派給學習本程式碼研究室的學員。講師可自由採取以下行動:

  • 視需要指派作業。
  • 告知學員如何繳交作業。
  • 為作業評分。

講師可以視需求使用全部或部分建議內容,也可以自由指派任何其他合適的作業。

如果您是自行學習本程式碼研究室,不妨利用這些作業驗收學習成果。

回答問題

第 1 題

你會以何種方式封裝儲存於 ViewModel 中的 LiveData,以便外部物件不需加以更新即可讀取資料?

  • 在 ViewModel 物件中,將資料的資料類型變更為 private LiveData。使用幕後屬性來公開型別 MutableLiveData 的唯讀資料。
  • 在 ViewModel 物件中,將資料的資料類型變更為 private MutableLiveData。使用幕後屬性來公開型別 LiveData 的唯讀資料。
  • 在 UI 控制器中,將資料的資料類型變更為 private MutableLiveData。使用幕後屬性來公開型別 LiveData 的唯讀資料。
  • 在 ViewModel 物件內部,將資料的資料型別變更為 LiveData。使用幕後屬性來公開型別 LiveData 的唯讀資料。

第 2 題

當 UI 控制器處於下列何種狀態時,LiveData 會更新 UI 控制器 (例如片段)?

  • 已重新啟用
  • 在背景中
  • 已暫停
  • 已停止

第 3 題

在 LiveData 觀察器模式中,可觀察的項目 (觀察對象) 為何?

  • Observer 方法
  • LiveData 物件中的資料
  • UI 控制器
  • ViewModel 物件

開始下一個課程:5.3:將資料繫結與 ViewModel 和 LiveData 互相整合

如要查看本課程其他程式碼研究室的連結,請參閱 Android Kotlin 基礎知識程式碼研究室登陸頁面。