Dasar-Dasar Android Kotlin 05.2: LiveData dan observer LiveData

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

Pengantar

Dalam codelab sebelumnya, Anda menggunakan ViewModel di aplikasi GuessTheWord untuk memungkinkan data aplikasi bertahan saat terjadi 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 tahu tampilan saat database pokok berubah.

Untuk menggunakan class LiveData, Anda menyiapkan "pengamat" (misalnya, aktivitas atau fragmen) yang mengamati perubahan pada data aplikasi. LiveData berbasis siklus proses, sehingga hanya mengupdate pengamat komponen aplikasi yang ada dalam status siklus proses aktif.

Yang harus sudah Anda ketahui

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

Yang akan Anda pelajari

  • Yang membuat objek LiveData berguna.
  • Cara menambahkan LiveData ke data yang disimpan dalam ViewModel.
  • Kapan 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 memperhatikan saat kata atau skor berubah.
  • Perbarui tampilan teks yang menampilkan nilai yang berubah.
  • Gunakan pola pengamat LiveData untuk menambahkan peristiwa selesai bermain game.
  • Terapkan tombol Play Again.

Dalam codelab Pelajaran 5, Anda akan mengembangkan aplikasi GuessTheWord, dimulai dengan kode awal. GuessTheWord adalah game gaya tebak gaya dua pemain, tempat pemain berkolaborasi untuk mencapai skor tertinggi.

Pemain pertama melihat kata-kata di aplikasi dan memeragakan setiap kata secara bergiliran, memastikan untuk tidak menunjukkan kata tersebut kepada pemain kedua. Pemain kedua mencoba menebak kata tersebut.

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

Pemain pertama memperagakan kata, dengan berhati-hati agar tidak mengucapkan kata itu sendiri.

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

Dalam codelab ini, Anda akan meningkatkan kualitas aplikasi GuessTheWord dengan menambahkan peristiwa untuk mengakhiri game saat pengguna melihat semua kata dalam aplikasi. Anda juga akan 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 Anda buat 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-nya.
  3. Perhatikan bahwa tombol Lewati menampilkan kata berikutnya dan mengurangi skor sebanyak satu, dan tombol Oke menampilkan kata berikutnya dan menambah skor sebanyak satu. Tombol Akhiri Game mengakhiri game.

LiveData adalah class holder data yang dapat diamati dan peka terhadap siklus proses. Misalnya, Anda dapat membungkus LiveData di sekitar skor saat ini dalam 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 mengupdate 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 dalam objek LiveData dengan mengonversi data skor saat ini dan kata saat ini di GameViewModel menjadi LiveData. Pada tugas selanjutnya, Anda akan menambahkan observer ke objek LiveData ini dan mempelajari cara mengamati LiveData.

Langkah 1: Ubah skor dan kata untuk menggunakan LiveData

  1. Di 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 berjenis LiveData. Pada langkah ini, Anda mengubah referensi ke variabel ini menggunakan properti value.

  1. Di GameViewModel, dalam metode onSkip(), ubah score menjadi score.value. Perhatikan error tentang score yang mungkin null. Anda akan memperbaiki error ini berikutnya.
  2. Untuk mengatasi error, tambahkan pemeriksaan null ke score.value di 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, 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 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 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. Kompilasikan dan jalankan aplikasi Anda. Fungsionalitas aplikasi harus sama seperti sebelumnya.

Tugas ini terkait erat dengan tugas sebelumnya, tempat Anda mengonversi data skor dan kata menjadi objek LiveData. Dalam tugas ini, Anda akan 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 letakkan 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), lalu impor androidx.lifecycle.Observer.

  1. Observer yang baru saja Anda buat menerima peristiwa saat data yang dimiliki 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 kata saat ini. Lakukan dengan cara yang sama seperti saat Anda 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(), serta semua referensi yang merujuknya. Anda tidak membutuhkannya lagi, karena tampilan teks diperbarui oleh metode observer LiveData.
  2. Jalankan aplikasi Anda. Aplikasi game Anda seharusnya bekerja persis seperti sebelumnya, tetapi sekarang menggunakan observer LiveData dan LiveData.

Encapsulation 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, class eksternal mana pun dapat mengubah variabel score dan word menggunakan properti value, misalnya menggunakan viewModel.score.value. Hal ini mungkin tidak menjadi masalah dalam aplikasi yang Anda kembangkan dalam codelab ini, tetapi dalam aplikasi produksi, Anda ingin mengontrol data dalam objek ViewModel.

Hanya ViewModel yang boleh mengedit data di aplikasi Anda. Namun, pengontrol UI perlu membaca data, sehingga kolom data tidak boleh sepenuhnya bersifat pribadi. Untuk mengumpulkan data aplikasi, Anda menggunakan objek MutableLiveData dan LiveData.

MutableLiveData vs. LiveData:

  • Data dalam objek MutableLiveData dapat diubah, seperti yang tersirat dalam 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 akan menerapkan properti pendukung untuk objek score dan word di aplikasi GuessTheWord.

Menambahkan properti pendukung ke skor dan kata

  1. Di GameViewModel, jadikan objek score saat ini private.
  2. Untuk mengikuti konvensi penamaan yang digunakan dalam properti pendukung, ubah score menjadi _score. Properti _score kini menjadi 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 setter-nya. Untuk mempelajari lebih lanjut pengambil dan penyetel di Kotlin, lihat Pengambil dan Penyetel.

    Untuk mengatasi error, ganti metode get() untuk objek score di GameViewModel dan kembalikan properti pendukung, _score.
val score: LiveData<Int>
   get() = _score
  1. Di GameViewModel, ubah referensi score ke versi internalnya yang dapat berubah, _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 untuknya, 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 sekali, Anda telah mengenkapsulasi objek LiveData word dan score.

Aplikasi Anda saat ini akan membuka layar skor saat pengguna mengetuk tombol Akhiri Game. Anda juga ingin aplikasi membuka layar skor saat pemain telah menyelesaikan semua kata. Setelah pemain selesai dengan kata terakhir, Anda ingin game berakhir secara otomatis sehingga pengguna tidak perlu mengetuk tombol.

Untuk menerapkan fungsi ini, Anda memerlukan peristiwa yang dipicu dan dikomunikasikan ke fragmen dari ViewModel saat semua kata telah ditampilkan. Untuk melakukannya, Anda menggunakan pola pengamat LiveData untuk memodelkan peristiwa selesai game.

Pola observer

Pola observer adalah pola desain software. Pola ini menentukan komunikasi antara objek: observable (subjek observasi) dan observer. Observable adalah objek yang memberi tahu observer tentang perubahan dalam statusnya.

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

Langkah 1: Gunakan LiveData untuk mendeteksi peristiwa game selesai

Dalam tugas ini, Anda menggunakan pola pengamat LiveData untuk memodelkan peristiwa game selesai.

  1. Di GameViewModel, buat objek Boolean MutableLiveData bernama _eventGameFinish. Objek ini akan menyimpan peristiwa game selesai.
  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, setel peristiwa game selesai, eventGameFinish, ke true.
/** Method for the game completed event **/
fun onGameFinish() {
   _eventGameFinish.value = true
}
  1. Di GameViewModel, 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 Anda, mainkan game-nya, dan selesaikan semua kata. Aplikasi akan otomatis membuka layar skor, bukan tetap berada di fragmen game hingga Anda mengetuk Akhiri Game.

    Setelah daftar kata kosong, eventGameFinish disetel, metode pengamat terkait di fragmen game dipanggil, dan aplikasi membuka fragmen layar.
  2. Kode yang Anda tambahkan telah menimbulkan masalah siklus proses. Untuk memahami masalah ini, di class GameFragment, jadikan kode navigasi sebagai komentar dalam metode gameFinished(). Pastikan untuk menyimpan pesan Toast dalam metode.
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 Anda, mainkan game-nya, dan selesaikan 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 melihat toast setiap saat. Ini adalah bug, karena toast hanya boleh ditampilkan sekali, saat game selesai. Toast tidak boleh ditampilkan setiap kali fragmen dibuat ulang. Anda akan mengatasi masalah ini di tugas berikutnya.

Langkah 2: Reset peristiwa selesai game

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

Inilah alasan mengapa toast game selesai 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 ulang, dan toast ditampilkan.

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

  1. Di GameViewModel, tambahkan metode onGameFinishComplete() untuk mereset peristiwa selesai bermain game, _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() diberi komentar untuk saat ini.)
private fun gameFinished() {
   ...
   viewModel.onGameFinishComplete()
}
  1. Jalankan aplikasi dan mainkan game-nya. Telusuri semua kata, lalu ubah orientasi layar perangkat. Toast hanya ditampilkan satu kali.
  2. Di GameFragment, di dalam metode gameFinished(), hapus komentar kode navigasi.

    Untuk menghapus komentar di Android Studio, pilih baris yang diberi komentar dan 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-nya. Pastikan aplikasi otomatis membuka layar skor akhir setelah Anda menyelesaikan semua kata.

Bagus! Aplikasi Anda menggunakan LiveData untuk memicu peristiwa game selesai guna berkomunikasi dari GameViewModel ke fragmen game bahwa daftar kata kosong. Fragmen game kemudian membuka fragmen skor.

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

Anda melakukan perubahan ini pada ScoreViewModel agar lengkap, sehingga semua data di aplikasi Anda menggunakan LiveData.

  1. Di ScoreViewModel, ubah jenis variabel score menjadi MutableLiveData. Ganti namanya berdasarkan 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 secara langsung menetapkan tampilan teks dengan nilai skor dari ViewModel.

Kode yang akan 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 Anda dan mainkan game-nya. Aplikasi akan berfungsi seperti sebelumnya, tetapi sekarang menggunakan LiveData dan observer untuk memperbarui skor.

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

Kode awal untuk aplikasi menyertakan tombol Play Again, tetapi tombol tersebut disembunyikan.

  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 guna berpindah dari layar skor ke layar game.
private val _eventPlayAgain = MutableLiveData<Boolean>()
val eventPlayAgain: LiveData<Boolean>
   get() = _eventPlayAgain
  1. Di ScoreViewModel, tentukan metode untuk menyetel dan mereset peristiwa, _eventPlayAgain.
fun onPlayAgain() {
   _eventPlayAgain.value = true
}
fun onPlayAgainComplete() {
   _eventPlayAgain.value = false
}
  1. Di ScoreFragment, tambahkan observer untuk eventPlayAgain. Letakkan 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 Anda dan mainkan game-nya. Setelah game selesai, layar skor akan menampilkan skor akhir dan tombol Main Lagi. Ketuk tombol PlayAgain, dan aplikasi akan membuka layar game sehingga Anda dapat memainkan game lagi.

Kerja bagus! Anda mengubah arsitektur aplikasi untuk menggunakan objek LiveData di ViewModel, dan Anda melampirkan pengamat 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 mengaktifkan UI agar diperbarui 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 mengupdate 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 Diamati

  • LiveData mengikuti pola pengamat. "Observable" adalah objek LiveData, dan pengamat adalah metode di pengontrol UI, seperti fragmen. Setiap kali data yang di-wrap di dalam LiveData berubah, metode pengamat di pengontrol UI akan diberi tahu.
  • Untuk membuat LiveData dapat diamati, lampirkan objek pengamat ke referensi LiveData di pengamat (seperti aktivitas dan fragmen) menggunakan metode observe().
  • Pola observer 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. Instruktur menentukan hal berikut:

  • Memberikan pekerjaan rumah jika diperlukan.
  • Memberi tahu siswa cara mengirimkan tugas pekerjaan rumah.
  • Memberi nilai tugas pekerjaan rumah.

Instruktur bisa menggunakan saran ini sesuai kebutuhan, dan bebas menugaskan pekerjaan rumah lain yang dirasa cocok.

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

Jawab pertanyaan-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 menjadi private LiveData. Gunakan properti pendukung untuk mengekspos data hanya baca jenis MutableLiveData.
  • Di dalam objek ViewModel, ubah jenis data menjadi private MutableLiveData. Gunakan properti pendukung untuk mengekspos data hanya baca jenis LiveData.
  • Di dalam pengontrol UI, ubah jenis data untuk data tersebut menjadi private MutableLiveData. Gunakan properti pendukung untuk mengekspos data hanya baca jenis LiveData.
  • Di dalam objek ViewModel, ubah jenis data menjadi LiveData. Gunakan properti pendukung untuk mengekspos data hanya baca jenis LiveData.

Pertanyaan 2

LiveData akan 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 pengamat LiveData, apa yang dimaksud dengan item yang dapat diamati (apa yang diamati)?

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

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

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