Dasar-Dasar Android Kotlin 05.2: Pengamat LiveData dan LiveData

Codelab ini adalah bagian dari kursus Dasar-Dasar Kotlin Android. Anda akan mendapatkan manfaat maksimal dari kursus ini jika Anda mengerjakan codelab secara berurutan. Semua codelab kursus tercantum di halaman landing codelab Dasar-Dasar Android Kotlin.

Pengantar

Di codelab sebelumnya, Anda menggunakan ViewModel di aplikasi GuessTheWord untuk memungkinkan data aplikasi bertahan dari perubahan konfigurasi perangkat. Dalam codelab ini, Anda akan mempelajari cara mengintegrasikan LiveData dengan data di class ViewModel. LiveData, yang merupakan salah satu Komponen Arsitektur Android, memungkinkan Anda membuat objek data yang memberi notifikasi tampilan saat terjadi perubahan database yang mendasarinya.

Untuk menggunakan class LiveData, siapkan "observers" (misalnya, aktivitas atau fragmen) yang mengamati perubahan dalam data aplikasi. LiveData berbasis siklus proses, sehingga hanya memperbarui observer komponen aplikasi yang dalam status siklus proses aktif.

Yang harus sudah Anda ketahui

  • Cara membuat aplikasi Android dasar di Kotlin.
  • Cara menavigasi antar-tujuan aplikasi.
  • Siklus proses Aktivitas dan Fragmen.
  • Cara menggunakan objek ViewModel di aplikasi Anda.
  • Cara membuat objek ViewModel menggunakan antarmuka ViewModelProvider.Factory.

Yang akan Anda pelajari

  • Apa yang membuat objek LiveData berguna.
  • Cara menambahkan LiveData ke data yang disimpan di ViewModel.
  • Waktu dan cara menggunakan MutableLiveData.
  • Cara menambahkan metode observer untuk mengamati perubahan di LiveData.
  • Cara mengenkapsulasi LiveData menggunakan properti pendukung.
  • Cara berkomunikasi antara pengontrol UI dan ViewModel yang sesuai.

Yang akan Anda lakukan

  • Gunakan LiveData untuk kata dan skor di aplikasi GuessTheWord.
  • Tambahkan observer yang melihat saat kata atau skor berubah.
  • Perbarui tampilan teks yang menampilkan nilai yang diubah.
  • Gunakan pola pengamat LiveData untuk menambahkan peristiwa yang diselesaikan game.
  • Terapkan tombol Play Again.

Dalam codelab Tutorial 5, Anda mengembangkan aplikasi GuessTheWord, dimulai dengan kode awal. GuessTheWord adalah game bergaya charade dua pemain, tempat pemain berkolaborasi untuk mencapai skor tertinggi.

Pemain pertama melihat kata dalam aplikasi dan memainkannya satu per satu, sehingga dia tidak akan menampilkan kata tersebut ke pemain kedua. Pemain kedua mencoba menebak kata.

Untuk memainkan game, pemain pertama membuka aplikasi di perangkat dan melihat kata, misalnya "gitar," seperti yang ditunjukkan pada screenshot di bawah ini.

Pemain pertama akan memainkannya, berhati-hatilah untuk tidak benar-benar mengucapkan kata itu sendiri.

  • Saat pemain kedua menebak kata dengan benar, pemain pertama menekan tombol Oke, yang akan meningkatkan jumlah satu kata dan menampilkan kata berikutnya.
  • Jika pemain kedua tidak dapat menebak kata, pemain pertama menekan tombol Lewati, yang mengurangi jumlah satu dan melewati ke kata berikutnya.
  • Untuk mengakhiri game, tekan tombol End Game. (Fungsi ini tidak ada dalam kode awal untuk codelab pertama dalam seri.)

Dalam codelab ini, Anda akan meningkatkan aplikasi GuessTheWord dengan menambahkan peristiwa untuk mengakhiri game saat pengguna menelusuri semua kata dalam aplikasi. Anda juga menambahkan tombol Play Again di fragmen skor, sehingga pengguna dapat memainkan game lagi.

Layar judul

Layar game

Layar skor

Dalam tugas ini, Anda akan menemukan dan menjalankan kode awal untuk codelab ini. Anda dapat menggunakan aplikasi GuessTheWord yang dibuat di codelab sebelumnya sebagai kode awal, atau Anda dapat mendownload aplikasi awal.

  1. (Opsional) Jika Anda tidak menggunakan kode dari codelab sebelumnya, download kode awal untuk codelab ini. Buka zip kode, lalu buka project di Android Studio.
  2. Jalankan aplikasi dan mainkan game.
  3. Perhatikan bahwa tombol Skip menampilkan kata berikutnya dan menurunkan skor sebesar satu, dan tombol Got it menunjukkan kata berikutnya dan meningkatkan skor sebesar satu. Tombol Akhiri Game mengakhiri game.

LiveData adalah class holder data yang dapat diamati dan peka terhadap siklus proses. Misalnya, Anda dapat menggabungkan LiveData dengan skor saat ini di aplikasi GuessTheWord. Dalam codelab ini, Anda akan mempelajari beberapa karakteristik LiveData:

  • LiveData dapat diamati, yang berarti bahwa observer akan diberi tahu saat data yang dimiliki objek LiveData berubah.
  • LiveData menyimpan data; LiveData adalah wrapper yang dapat digunakan dengan data apa pun
  • LiveData berbasis siklus proses, yang berarti hanya memperbarui observer yang ada dalam status siklus proses aktif seperti STARTED atau RESUMED.

Dalam tugas ini, Anda akan mempelajari cara menggabungkan jenis data apa pun ke objek LiveData dengan mengonversi skor saat ini dan data kata saat ini di GameViewModel menjadi LiveData. Pada tugas selanjutnya, Anda menambahkan observer ke objek LiveData ini dan mempelajari cara mengobservasi LiveData.

Langkah 1: Ubah skor dan kata untuk menggunakan LiveData

  1. Pada paket screens/game, buka file GameViewModel.
  2. Ubah jenis variabel score dan word menjadi MutableLiveData.

    MutableLiveData adalah LiveData yang nilainya dapat diubah. MutableLiveData adalah class generik, jadi Anda perlu menentukan jenis data yang disimpannya.
// The current word
val word = MutableLiveData<String>()
// The current score
val score = MutableLiveData<Int>()
  1. Di GameViewModel, di dalam blok init, lakukan inisialisasi score dan word. Untuk mengubah nilai variabel LiveData, Anda menggunakan metode setValue() pada variabel. Di Kotlin, Anda dapat memanggil setValue() menggunakan properti value.
init {

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

Langkah 2: Perbarui referensi objek LiveData

Variabel score dan word sekarang menjadi jenis LiveData. Pada langkah ini, Anda mengubah referensi ke variabel tersebut, menggunakan properti value.

  1. Di GameViewModel, di metode onSkip(), ubah score menjadi score.value. Perhatikan error tentang score yang mungkin adalah null. Anda akan memperbaiki error ini berikutnya.
  2. Untuk mengatasi error, tambahkan pemeriksaan null ke score.value dalam onSkip(). Kemudian panggil fungsi minus() pada score, yang melakukan pengurangan dengan keamanan null.
fun onSkip() {
   if (!wordList.isEmpty()) {
       score.value = (score.value)?.minus(1)
   }
   nextWord()
}
  1. Perbarui metode onCorrect() dengan cara yang sama: tambahkan pemeriksaan null ke variabel score dan gunakan fungsi plus().
fun onCorrect() {
   if (!wordList.isEmpty()) {
       score.value = (score.value)?.plus(1)
   }
   nextWord()
}
  1. Di GameViewModel, di dalam metode nextWord(), ubah referensi word menjadi word.value.
private fun nextWord() {
   if (!wordList.isEmpty()) {
       //Select and remove a word from the list
       word.value = wordList.removeAt(0)
   }
}
  1. Di GameFragment, dalam metode updateWordText(), ubah referensi menjadi viewModel.word menjadi viewModel.word.value.
/** Methods for updating the UI **/
private fun updateWordText() {
   binding.wordText.text = viewModel.word.value
}
  1. Di GameFragment, dalam metode updateScoreText(), ubah referensi ke viewModel.score menjadi viewModel.score.value.
private fun updateScoreText() {
   binding.scoreText.text = viewModel.score.value.toString()
}
  1. Di GameFragment, dalam metode gameFinished(), ubah referensi menjadi viewModel.score menjadi viewModel.score.value. Tambahkan pemeriksaan keselamatan null yang diperlukan.
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. Pastikan tidak ada error dalam kode Anda. Kompilasi dan jalankan aplikasi Anda. Fungsi aplikasi harus sama seperti sebelumnya.

Tugas ini berkaitan erat dengan tugas sebelumnya, tempat Anda mengonversi skor dan data kata menjadi objek LiveData. Dalam tugas ini, Anda melampirkan objek Observer ke objek LiveData tersebut.

  1. Di GameFragment, dalam metode onCreateView(), lampirkan objek Observer ke objek LiveData untuk skor saat ini, viewModel.score. Gunakan metode observe() dan masukkan kode setelah inisialisasi viewModel. Gunakan ekspresi lambda untuk menyederhanakan kode. (Ekspresi lambda adalah fungsi anonim yang tidak dideklarasikan, tetapi langsung diteruskan sebagai ekspresi.)
viewModel.score.observe(this, Observer { newScore ->
})

Selesaikan referensi ke Observer. Untuk melakukannya, klik Observer, tekan Alt+Enter (Option+Enter di Mac), dan impor androidx.lifecycle.Observer.

  1. Observer yang baru saja Anda buat akan menerima peristiwa bila data yang dimiliki oleh objek LiveData yang diamati berubah. Di dalam observer, perbarui skor TextView dengan skor baru.
/** Setting up LiveData observation relationship **/
viewModel.score.observe(this, Observer { newScore ->
   binding.scoreText.text = newScore.toString()
})
  1. Lampirkan objek Observer ke objek LiveData saat ini. Lakukan dengan cara yang sama seperti saat melampirkan objek Observer ke skor saat ini.
/** Setting up LiveData observation relationship **/
viewModel.word.observe(this, Observer { newWord ->
   binding.wordText.text = newWord
})

Saat nilai score atau word berubah, score atau word yang ditampilkan di layar kini diperbarui secara otomatis.

  1. Di GameFragment, hapus metode updateWordText() dan updateScoreText(), dan semua referensi ke dalamnya. Anda tidak memerlukannya lagi, karena tampilan teks diperbarui oleh metode observer LiveData.
  2. Jalankan aplikasi Anda. Aplikasi game Anda seharusnya bekerja persis seperti sebelumnya, tetapi sekarang aplikasi ini menggunakan observer LiveData dan LiveData.

Enkapsulasi adalah cara untuk membatasi akses langsung ke beberapa kolom objek. Saat mengenkapsulasi objek, Anda menampilkan sekumpulan metode publik yang mengubah kolom internal pribadi. Dengan menggunakan enkapsulasi, Anda mengontrol cara class lain memanipulasi kolom internal ini.

Dalam kode saat ini, semua class eksternal dapat mengubah variabel score dan word menggunakan properti value, misalnya menggunakan viewModel.score.value. Ini mungkin tidak masalah dalam aplikasi yang Anda kembangkan di codelab ini, tetapi di aplikasi produksi, Anda menginginkan kontrol atas data di objek ViewModel.

Hanya ViewModel yang boleh mengedit data di aplikasi Anda. Namun, pengontrol UI harus membaca data agar kolom data tidak sepenuhnya bersifat pribadi. Untuk mengenkapsulasi data aplikasi, Anda dapat menggunakan objek MutableLiveData dan LiveData.

MutableLiveData dibandingkan LiveData:

  • Data dalam objek MutableLiveData dapat diubah, seperti namanya. Di dalam ViewModel, data harus dapat diedit, sehingga menggunakan MutableLiveData.
  • Data dalam objek LiveData dapat dibaca, tetapi tidak dapat diubah. Dari luar ViewModel, data harus dapat dibaca, tetapi tidak dapat diedit, sehingga data harus ditampilkan sebagai LiveData.

Untuk menjalankan strategi ini, Anda menggunakan properti pendukung Kotlin. Properti pendukung memungkinkan Anda menampilkan sesuatu dari pengambil selain dari objek yang tepat. Dalam tugas ini, Anda menerapkan properti pendukung untuk objek score dan word di aplikasi GuessTheWord.

Menambahkan properti pendukung ke skor dan kata

  1. Di GameViewModel, buat objek score saat ini private.
  2. Untuk mengikuti konvensi penamaan yang digunakan dalam properti pendukung, ubah score menjadi _score. Properti _score kini merupakan versi skor game yang dapat diubah, untuk digunakan secara internal.
  3. Buat versi publik dari jenis LiveData, yang disebut score.
// The current score
private val _score = MutableLiveData<Int>()
val score: LiveData<Int>
  1. Anda melihat error inisialisasi. Error ini terjadi karena di dalam GameFragment, score adalah referensi LiveData, dan score tidak dapat lagi mengakses penyetelnya. Untuk mempelajari pengambil dan penyetel di Kotlin lebih lanjut, lihat Pengambil dan Penyetel.

    Untuk mengatasi error, ganti metode get() untuk objek score di GameViewModel dan tampilkan properti pendukung, _score.
val score: LiveData<Int>
   get() = _score
  1. Di GameViewModel, ubah referensi score ke versi internalnya yang dapat diubah, _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. Ganti nama objek word menjadi _word dan tambahkan properti pendukung untuk objek tersebut, seperti yang Anda lakukan untuk objek 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)
   }
}

Bagus, Anda telah mengenkapsulasi objek LiveData word dan score.

Aplikasi saat ini akan membuka layar skor saat pengguna mengetuk tombol End Game. Anda juga ingin aplikasi menavigasi ke layar skor saat pemain melihat semua kata. Setelah pemain menyelesaikan kata terakhir, Anda ingin game berakhir secara otomatis sehingga pengguna tidak perlu mengetuk tombol tersebut.

Untuk mengimplementasikan fungsi ini, Anda perlu peristiwa dipicu dan dikomunikasikan ke fragmen dari ViewModel saat semua kata telah ditampilkan. Untuk melakukannya, gunakan pola observer LiveData untuk membuat model peristiwa akhir game.

Pola pengamat

Pola pengamatan adalah pola desain software. Ini menentukan komunikasi antara objek: yang dapat diamati ("subject" observasi) dan observer. observable adalah objek yang memberi tahu observer tentang perubahan dalam statusnya.

Dalam kasus LiveData di aplikasi ini, objek yang dapat diamati (subjek) adalah objek LiveData, dan pengamat adalah metode dalam pengontrol UI, seperti fragmen. Perubahan status terjadi setiap kali data yang digabungkan dalam LiveData berubah. Class LiveData sangat penting dalam berkomunikasi dari ViewModel ke fragmen.

Langkah 1: Gunakan LiveData untuk mendeteksi peristiwa akhir game

Dalam tugas ini, Anda menggunakan pola observer LiveData untuk membuat model peristiwa akhir game.

  1. Di GameViewModel, buat objek Boolean MutableLiveData bernama _eventGameFinish. Objek ini akan menyimpan peristiwa yang sudah diselesaikan game.
  2. Setelah menginisialisasi objek _eventGameFinish, buat dan inisialisasi properti pendukung yang disebut eventGameFinish.
// Event which triggers the end of the game
private val _eventGameFinish = MutableLiveData<Boolean>()
val eventGameFinish: LiveData<Boolean>
   get() = _eventGameFinish
  1. Di GameViewModel, tambahkan metode onGameFinish(). Dalam metode ini, tetapkan peristiwa yang sudah selesai game, eventGameFinish, ke true.
/** Method for the game completed event **/
fun onGameFinish() {
   _eventGameFinish.value = true
}
  1. Di GameViewModel, di dalam metode nextWord(), akhiri game jika daftar kata kosong.
private fun nextWord() {
   if (wordList.isEmpty()) {
       onGameFinish()
   } else {
       //Select and remove a _word from the list
       _word.value = wordList.removeAt(0)
   }
}
  1. Di GameFragment, di dalam onCreateView(), setelah menginisialisasi viewModel, lampirkan observer ke eventGameFinish. Gunakan metode observe(). Di dalam fungsi lambda, panggil metode gameFinished().
// Observer for the Game finished event
viewModel.eventGameFinish.observe(this, Observer<Boolean> { hasFinished ->
   if (hasFinished) gameFinished()
})
  1. Jalankan aplikasi, mainkan game, dan ikuti semua kata. Aplikasi akan otomatis membuka layar skor, bukan tetap berada dalam fragmen game hingga Anda mengetuk End Game.

    Setelah daftar kata kosong, eventGameFinish ditetapkan, metode pengamat terkait dalam fragmen game akan dipanggil, dan aplikasi akan membuka fragmen layar.
  2. Kode yang Anda tambahkan telah memperkenalkan masalah siklus proses. Untuk memahami masalah ini, jadikan kode navigasi dalam metode gameFinished() sebagai komentar di class GameFragment. Pastikan untuk mempertahankan pesan Toast dalam metode ini.
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. Jalankan aplikasi, mainkan game, dan ikuti semua kata. Pesan toast yang bertuliskan "Game baru saja selesai" muncul sebentar di bagian bawah layar game, yang merupakan perilaku yang diharapkan.

Sekarang putar perangkat atau emulator. Toast ditampilkan lagi. Putar perangkat beberapa kali lagi, dan Anda mungkin akan selalu melihat toast. Ini adalah bug, karena toast hanya akan ditampilkan sekali, ketika game selesai. Toast tidak akan ditampilkan setiap kali fragmen dibuat ulang. Anda menyelesaikan masalah ini di tugas berikutnya.

Langkah 2: Reset acara yang telah selesai dengan game

Biasanya, LiveData mengirimkan update ke observer hanya jika data berubah. Pengecualian perilaku ini adalah saat pengamat juga menerima update saat pengamat berubah dari status nonaktif menjadi aktif.

Inilah sebabnya toast yang diselesaikan game dipicu berulang kali di aplikasi Anda. Saat fragmen game dibuat ulang setelah rotasi layar, fragmen tersebut berpindah dari status tidak aktif ke status aktif. Observer dalam fragmen terhubung kembali ke ViewModel yang ada dan menerima data saat ini. Metode gameFinished() dipicu kembali, dan toast akan ditampilkan.

Dalam tugas ini, Anda memperbaiki masalah ini dan menampilkan toast hanya sekali, dengan mereset flag eventGameFinish di GameViewModel.

  1. Di GameViewModel, tambahkan metode onGameFinishComplete() untuk mereset acara yang telah selesai, _eventGameFinish.
/** Method for the game completed event **/

fun onGameFinishComplete() {
   _eventGameFinish.value = false
}
  1. Di GameFragment, di akhir gameFinished(), panggil onGameFinishComplete() pada objek viewModel. (Biarkan kode navigasi di gameFinished() dikomentari untuk saat ini.)
private fun gameFinished() {
   ...
   viewModel.onGameFinishComplete()
}
  1. Jalankan aplikasi dan mainkan game. Periksa semua kata, lalu ubah orientasi layar perangkat. Toast hanya ditampilkan sekali.
  2. Di GameFragment, dalam metode gameFinished(), hapus tanda komentar kode navigasi.

    Untuk menghapus tanda komentar di Android Studio, pilih baris yang diberi komentar, lalu tekan Control+/ (Command+/ di Mac).
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()
}

Jika diminta oleh Android Studio, impor androidx.navigation.fragment.NavHostFragment.findNavController.

  1. Jalankan aplikasi dan mainkan game. Pastikan aplikasi membuka layar skor akhir secara otomatis setelah Anda melihat semua kata.

Bagus! Aplikasi Anda menggunakan LiveData untuk memicu peristiwa akhir game untuk berkomunikasi dari GameViewModel ke fragmen game yang daftar katanya kosong. Fragmen game kemudian membuka fragmen skor.

Dalam tugas ini, Anda mengubah skor ke objek LiveData di ScoreViewModel dan melampirkan observer ke objek tersebut. Tugas ini mirip dengan yang Anda lakukan saat menambahkan LiveData ke GameViewModel.

Anda membuat perubahan ini pada ScoreViewModel untuk kelengkapan, sehingga semua data di aplikasi Anda menggunakan LiveData.

  1. Di ScoreViewModel, ubah jenis variabel score menjadi MutableLiveData. Ganti namanya menurut konvensi menjadi _score dan tambahkan properti pendukung.
private val _score = MutableLiveData<Int>()
val score: LiveData<Int>
   get() = _score
  1. Di ScoreViewModel, di dalam blok init, lakukan inisialisasi _score. Anda dapat menghapus atau membiarkan log di blok init sesuai keinginan.
init {
   _score.value = finalScore
}
  1. Di ScoreFragment, di dalam onCreateView(), setelah menginisialisasi viewModel, lampirkan observer untuk objek skor LiveData. Di dalam ekspresi lambda, tetapkan nilai skor ke tampilan teks skor. Hapus kode yang langsung menetapkan tampilan teks dengan nilai skor dari ViewModel.

Kode untuk ditambahkan:

// Add observer for score
viewModel.score.observe(this, Observer { newScore ->
   binding.scoreText.text = newScore.toString()
})

Kode yang akan dihapus:

binding.scoreText.text = viewModel.score.toString()

Saat diminta oleh Android Studio, impor androidx.lifecycle.Observer.

  1. Jalankan aplikasi dan mainkan game. Aplikasi seharusnya berfungsi seperti sebelumnya, tetapi sekarang aplikasi menggunakan LiveData dan observer untuk memperbarui skor.

Dalam tugas ini, Anda menambahkan tombol Play Again ke layar skor dan mengimplementasikan pemroses kliknya menggunakan peristiwa LiveData. Tombol tersebut memicu peristiwa untuk berpindah dari layar skor ke layar game.

Kode awal untuk aplikasi menyertakan tombol Play Again, tetapi tombolnya tersembunyi.

  1. Di res/layout/score_fragment.xml, untuk tombol play_again_button, ubah nilai atribut visibility menjadi visible.
<Button
   android:id="@+id/play_again_button"
...
   android:visibility="visible"
 />
  1. Di ScoreViewModel, tambahkan objek LiveData untuk menyimpan Boolean yang disebut _eventPlayAgain. Objek ini digunakan untuk menyimpan peristiwa LiveData untuk membuka layar skor ke layar game.
private val _eventPlayAgain = MutableLiveData<Boolean>()
val eventPlayAgain: LiveData<Boolean>
   get() = _eventPlayAgain
  1. Di ScoreViewModel, tentukan metode untuk menetapkan dan mereset peristiwa, _eventPlayAgain.
fun onPlayAgain() {
   _eventPlayAgain.value = true
}
fun onPlayAgainComplete() {
   _eventPlayAgain.value = false
}
  1. Di ScoreFragment, tambahkan pengamat untuk eventPlayAgain. Masukkan kode di akhir onCreateView(), sebelum pernyataan return. Di dalam ekspresi lambda, kembali ke layar game dan reset eventPlayAgain.
// Navigates back to game when button is pressed
viewModel.eventPlayAgain.observe(this, Observer { playAgain ->
   if (playAgain) {
      findNavController().navigate(ScoreFragmentDirections.actionRestart())
       viewModel.onPlayAgainComplete()
   }
})

Impor androidx.navigation.fragment.findNavController saat diminta oleh Android Studio.

  1. Di ScoreFragment, di dalam onCreateView(), tambahkan pemroses klik ke tombol PlayAgain dan panggil viewModel.onPlayAgain().
binding.playAgainButton.setOnClickListener {  viewModel.onPlayAgain()  }
  1. Jalankan aplikasi dan mainkan game. Setelah game selesai, layar skor akan menampilkan skor akhir dan tombol Play Again. Ketuk tombol PlayAgain, dan aplikasi akan berpindah ke layar game sehingga Anda dapat memainkan game lagi.

Kerja bagus! Anda mengubah arsitektur aplikasi untuk menggunakan objek LiveData di ViewModel, dan melampirkan observer ke objek LiveData. LiveData memberi tahu objek observer saat nilai yang dimiliki oleh LiveData berubah.

Project Android Studio: GuessTheWord

LiveData

  • LiveData adalah class holder data yang dapat diamati dan peka terhadap siklus proses, salah satu Komponen Arsitektur Android.
  • Anda dapat menggunakan LiveData untuk memungkinkan UI Anda diupdate secara otomatis saat data diperbarui.
  • LiveData dapat diamati, yang berarti bahwa observer seperti aktivitas atau fragmen dapat diberi tahu saat data yang dimiliki objek LiveData berubah.
  • LiveData menyimpan data; ini adalah wrapper yang dapat digunakan dengan data apa pun.
  • LiveData berbasis siklus proses, yang berarti hanya memperbarui observer yang ada dalam status siklus proses aktif seperti STARTED atau RESUMED.

Untuk menambahkan LiveData

  • Ubah jenis variabel data di ViewModel menjadi LiveData atau MutableLiveData.

MutableLiveData adalah objek LiveData yang nilainya dapat diubah. MutableLiveData adalah class generik, jadi Anda perlu menentukan jenis data yang disimpannya.

  • Untuk mengubah nilai data yang disimpan oleh LiveData, gunakan metode setValue() pada variabel LiveData.

Untuk mengenkapsulasi LiveData

  • LiveData di dalam ViewModel harus dapat diedit. Di luar ViewModel, LiveData harus dapat dibaca. Hal ini dapat diimplementasikan menggunakan properti pendukung Kotlin.
  • Properti pendukung Kotlin memungkinkan Anda menampilkan sesuatu dari pengambil selain dari objek yang tepat.
  • Untuk mengenkapsulasi LiveData, gunakan private MutableLiveData di dalam ViewModel dan tampilkan properti pendukung LiveData di luar ViewModel.

LiveData yang dapat diobservasi

  • LiveData mengikuti pola pengamat. "observable" adalah objek LiveData, dan pengamat adalah metode dalam pengontrol UI, seperti fragmen. Setiap kali data yang digabungkan dalam LiveData berubah, metode pengamat di pengontrol UI akan diberi tahu.
  • Agar LiveData dapat diamati, lampirkan objek observer ke referensi LiveData dalam observer (seperti aktivitas dan fragmen) menggunakan metode observe().
  • Pola pengamat LiveData ini dapat digunakan untuk berkomunikasi dari ViewModel ke pengontrol UI.

Kursus Udacity:

Dokumentasi developer Android:

Lainnya:

Bagian ini mencantumkan kemungkinan tugas pekerjaan rumah untuk siswa yang mengerjakan codelab ini sebagai bagian dari kursus yang dipimpin oleh instruktur. Terserah instruktur untuk melakukan hal berikut:

  • Tugaskan pekerjaan rumah jika diperlukan.
  • Berkomunikasi dengan siswa cara mengirimkan tugas pekerjaan rumah.
  • Beri nilai tugas pekerjaan rumah.

Instruktur dapat menggunakan saran ini sesedikit atau sebanyak yang mereka inginkan, dan harus bebas memberikan pekerjaan rumah lain yang dirasa sesuai.

Jika Anda mengerjakan codelab ini sendiri, silakan gunakan tugas pekerjaan rumah ini untuk menguji pengetahuan Anda.

Jawab pertanyaan berikut

Pertanyaan 1

Bagaimana Anda mengenkapsulasi LiveData yang disimpan di ViewModel sehingga objek eksternal dapat membaca data tanpa dapat memperbaruinya?

  • Di dalam objek ViewModel, ubah jenis data data menjadi private LiveData. Gunakan properti backing untuk mengekspos data hanya baca jenis MutableLiveData.
  • Di dalam objek ViewModel, ubah jenis data data menjadi private MutableLiveData. Gunakan properti backing untuk mengekspos data hanya baca jenis LiveData.
  • Di dalam pengontrol UI, ubah jenis data data menjadi private MutableLiveData. Gunakan properti backing untuk mengekspos data hanya baca jenis LiveData.
  • Di dalam objek ViewModel, ubah jenis data data menjadi LiveData. Gunakan properti backing untuk mengekspos data hanya baca jenis LiveData.

Pertanyaan 2

LiveData mengupdate pengontrol UI (seperti fragmen) jika pengontrol UI berada dalam status mana dari berikut ini?

  • Dilanjutkan
  • Di latar belakang
  • Dijeda
  • Dihentikan

Pertanyaan 3

Dalam pola observer LiveData, item apa yang dapat diamati (apa yang diamati)?

  • Metode pengamat
  • Data dalam objek LiveData
  • Pengontrol UI
  • Objek ViewModel

Mulai tutorial berikutnya: 5.3: Data binding dengan ViewModel dan LiveData

Untuk link ke codelab lainnya dalam kursus ini, lihat halaman landing codelab Dasar-Dasar Kotlin Android.