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 antarmukaViewModelProvider.Factory
.
Yang akan Anda pelajari
- Yang membuat objek
LiveData
berguna. - Cara menambahkan
LiveData
ke data yang disimpan dalamViewModel
. - 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.
- (Opsional) Jika Anda tidak menggunakan kode dari codelab sebelumnya, download kode awal untuk codelab ini. Buka zip kode, lalu buka project di Android Studio.
- Jalankan aplikasi dan mainkan game-nya.
- 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 objekLiveData
berubah.LiveData
menyimpan data;LiveData
adalah wrapper yang dapat digunakan dengan data apa punLiveData
berbasis siklus proses, yang berarti hanya mengupdate observer yang ada dalam status siklus proses aktif sepertiSTARTED
atauRESUMED
.
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
- Di paket
screens/game
, buka fileGameViewModel
. - Ubah jenis variabel
score
danword
menjadiMutableLiveData
.MutableLiveData
adalahLiveData
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>()
- Di
GameViewModel
, di dalam blokinit
, lakukan inisialisasiscore
danword
. Untuk mengubah nilai variabelLiveData
, Anda menggunakan metodesetValue()
pada variabel. Di Kotlin, Anda dapat memanggilsetValue()
menggunakan propertivalue
.
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
.
- Di
GameViewModel
, dalam metodeonSkip()
, ubahscore
menjadiscore.value
. Perhatikan error tentangscore
yang mungkinnull
. Anda akan memperbaiki error ini berikutnya. - Untuk mengatasi error, tambahkan pemeriksaan
null
kescore.value
dionSkip()
. Kemudian, panggil fungsiminus()
padascore
, yang melakukan pengurangan dengan keamanannull
.
fun onSkip() {
if (!wordList.isEmpty()) {
score.value = (score.value)?.minus(1)
}
nextWord()
}
- Perbarui metode
onCorrect()
dengan cara yang sama: tambahkan pemeriksaannull
ke variabelscore
dan gunakan fungsiplus()
.
fun onCorrect() {
if (!wordList.isEmpty()) {
score.value = (score.value)?.plus(1)
}
nextWord()
}
- Di
GameViewModel
, dalam metodenextWord()
, ubah referensiword
menjadiword
.
value
.
private fun nextWord() {
if (!wordList.isEmpty()) {
//Select and remove a word from the list
word.value = wordList.removeAt(0)
}
}
- Di
GameFragment
, dalam metodeupdateWordText()
, ubah referensiviewModel
.word
menjadiviewModel
.
word
.
value.
/** Methods for updating the UI **/
private fun updateWordText() {
binding.wordText.text = viewModel.word.value
}
- Di
GameFragment
, dalam metodeupdateScoreText()
, ubah referensi keviewModel
.score
menjadiviewModel
.
score
.
value.
private fun updateScoreText() {
binding.scoreText.text = viewModel.score.value.toString()
}
- Di
GameFragment
, dalam metodegameFinished()
, ubah referensiviewModel
.score
menjadiviewModel
.
score
.
value
. Tambahkan pemeriksaan keselamatannull
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)
}
- 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.
- Di
GameFragment,
dalam metodeonCreateView()
, lampirkan objekObserver
ke objekLiveData
untuk skor saat ini,viewModel.score
. Gunakan metodeobserve()
, dan letakkan kode setelah inisialisasiviewModel
. 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
.
- Observer yang baru saja Anda buat menerima peristiwa saat data yang dimiliki objek
LiveData
yang diamati berubah. Di dalam observer, perbarui skorTextView
dengan skor baru.
/** Setting up LiveData observation relationship **/
viewModel.score.observe(this, Observer { newScore ->
binding.scoreText.text = newScore.toString()
})
- Lampirkan objek
Observer
ke objekLiveData
kata saat ini. Lakukan dengan cara yang sama seperti saat Anda melampirkan objekObserver
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.
- Di
GameFragment
, hapus metodeupdateWordText()
danupdateScoreText()
, serta semua referensi yang merujuknya. Anda tidak membutuhkannya lagi, karena tampilan teks diperbarui oleh metode observerLiveData
. - Jalankan aplikasi Anda. Aplikasi game Anda seharusnya bekerja persis seperti sebelumnya, tetapi sekarang menggunakan observer
LiveData
danLiveData
.
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 dalamViewModel
, data harus dapat diedit, sehingga menggunakanMutableLiveData
. - Data dalam objek
LiveData
dapat dibaca, tetapi tidak dapat diubah. Dari luarViewModel
, data harus dapat dibaca, tetapi tidak dapat diedit, sehingga data harus ditampilkan sebagaiLiveData
.
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
- Di
GameViewModel
, jadikan objekscore
saat iniprivate
. - 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. - Buat versi publik dari jenis
LiveData
, yang disebutscore
.
// The current score
private val _score = MutableLiveData<Int>()
val score: LiveData<Int>
- Anda melihat error inisialisasi. Error ini terjadi karena di dalam
GameFragment
,score
adalah referensiLiveData
, danscore
tidak dapat lagi mengakses setter-nya. Untuk mempelajari lebih lanjut pengambil dan penyetel di Kotlin, lihat Pengambil dan Penyetel.
Untuk mengatasi error, ganti metodeget()
untuk objekscore
diGameViewModel
dan kembalikan properti pendukung,_score
.
val score: LiveData<Int>
get() = _score
- Di
GameViewModel
, ubah referensiscore
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)
}
...
}
- Ganti nama objek
word
menjadi_word
dan tambahkan properti pendukung untuknya, seperti yang Anda lakukan untuk objekscore
.
// 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.
- Di
GameViewModel
, buat objekBoolean
MutableLiveData
bernama_eventGameFinish
. Objek ini akan menyimpan peristiwa game selesai. - Setelah menginisialisasi objek
_eventGameFinish
, buat dan inisialisasi properti pendukung yang disebuteventGameFinish
.
// Event which triggers the end of the game
private val _eventGameFinish = MutableLiveData<Boolean>()
val eventGameFinish: LiveData<Boolean>
get() = _eventGameFinish
- Di
GameViewModel
, tambahkan metodeonGameFinish()
. Dalam metode ini, setel peristiwa game selesai,eventGameFinish
, ketrue
.
/** Method for the game completed event **/
fun onGameFinish() {
_eventGameFinish.value = true
}
- Di
GameViewModel
, dalam metodenextWord()
, 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)
}
}
- Di
GameFragment
, di dalamonCreateView()
, setelah menginisialisasiviewModel
, lampirkan observer keeventGameFinish
. Gunakan metodeobserve()
. Di dalam fungsi lambda, panggil metodegameFinished()
.
// Observer for the Game finished event
viewModel.eventGameFinish.observe(this, Observer<Boolean> { hasFinished ->
if (hasFinished) gameFinished()
})
- 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. - Kode yang Anda tambahkan telah menimbulkan masalah siklus proses. Untuk memahami masalah ini, di class
GameFragment
, jadikan kode navigasi sebagai komentar dalam metodegameFinished()
. Pastikan untuk menyimpan pesanToast
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)
}
- 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
.
- Di
GameViewModel
, tambahkan metodeonGameFinishComplete()
untuk mereset peristiwa selesai bermain game,_eventGameFinish
.
/** Method for the game completed event **/
fun onGameFinishComplete() {
_eventGameFinish.value = false
}
- Di
GameFragment
, di akhirgameFinished()
, panggilonGameFinishComplete()
pada objekviewModel
. (Biarkan kode navigasi digameFinished()
diberi komentar untuk saat ini.)
private fun gameFinished() {
...
viewModel.onGameFinishComplete()
}
- Jalankan aplikasi dan mainkan game-nya. Telusuri semua kata, lalu ubah orientasi layar perangkat. Toast hanya ditampilkan satu kali.
- Di
GameFragment
, di dalam metodegameFinished()
, hapus komentar kode navigasi.
Untuk menghapus komentar di Android Studio, pilih baris yang diberi komentar dan tekanControl+/
(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
.
- 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
.
- Di
ScoreViewModel
, ubah jenis variabelscore
menjadiMutableLiveData
. Ganti namanya berdasarkan konvensi menjadi_score
dan tambahkan properti pendukung.
private val _score = MutableLiveData<Int>()
val score: LiveData<Int>
get() = _score
- Di
ScoreViewModel
, di dalam blokinit
, lakukan inisialisasi_score
. Anda dapat menghapus atau membiarkan log di blokinit
sesuai keinginan.
init {
_score.value = finalScore
}
- Di
ScoreFragment
, di dalamonCreateView()
, setelah menginisialisasiviewModel
, lampirkan observer untuk objek skorLiveData
. Di dalam ekspresi lambda, tetapkan nilai skor ke tampilan teks skor. Hapus kode yang secara langsung menetapkan tampilan teks dengan nilai skor dariViewModel
.
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
.
- 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.
- Di
res/layout/score_fragment.xml
, untuk tombolplay_again_button
, ubah nilai atributvisibility
menjadivisible
.
<Button
android:id="@+id/play_again_button"
...
android:visibility="visible"
/>
- Di
ScoreViewModel
, tambahkan objekLiveData
untuk menyimpanBoolean
yang disebut_eventPlayAgain
. Objek ini digunakan untuk menyimpan peristiwaLiveData
guna berpindah dari layar skor ke layar game.
private val _eventPlayAgain = MutableLiveData<Boolean>()
val eventPlayAgain: LiveData<Boolean>
get() = _eventPlayAgain
- Di
ScoreViewModel
, tentukan metode untuk menyetel dan mereset peristiwa,_eventPlayAgain
.
fun onPlayAgain() {
_eventPlayAgain.value = true
}
fun onPlayAgainComplete() {
_eventPlayAgain.value = false
}
- Di
ScoreFragment
, tambahkan observer untukeventPlayAgain
. Letakkan kode di akhironCreateView()
, sebelum pernyataanreturn
. Di dalam ekspresi lambda, kembali ke layar game dan reseteventPlayAgain
.
// 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.
- Di
ScoreFragment
, di dalamonCreateView()
, tambahkan pemroses klik ke tombol PlayAgain dan panggilviewModel
.onPlayAgain()
.
binding.playAgainButton.setOnClickListener { viewModel.onPlayAgain() }
- 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 objekLiveData
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 sepertiSTARTED
atauRESUMED
.
Untuk menambahkan LiveData
- Ubah jenis variabel data di
ViewModel
menjadiLiveData
atauMutableLiveData
.
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 metodesetValue()
pada variabelLiveData
.
Untuk mengenkapsulasi LiveData
LiveData
di dalamViewModel
harus dapat diedit. Di luarViewModel
,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
, gunakanprivate
MutableLiveData
di dalamViewModel
dan tampilkan properti pendukungLiveData
di luarViewModel
.
LiveData yang Dapat Diamati
LiveData
mengikuti pola pengamat. "Observable" adalah objekLiveData
, dan pengamat adalah metode di pengontrol UI, seperti fragmen. Setiap kali data yang di-wrap di dalamLiveData
berubah, metode pengamat di pengontrol UI akan diberi tahu.- Untuk membuat
LiveData
dapat diamati, lampirkan objek pengamat ke referensiLiveData
di pengamat (seperti aktivitas dan fragmen) menggunakan metodeobserve()
. - Pola observer
LiveData
ini dapat digunakan untuk berkomunikasi dariViewModel
ke pengontrol UI.
Kursus Udacity:
Dokumentasi developer Android:
Lainnya:
- Properti pendukung di Kotlin
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 menjadiprivate
LiveData
. Gunakan properti pendukung untuk mengekspos data hanya baca jenisMutableLiveData
. - Di dalam objek
ViewModel
, ubah jenis data menjadiprivate
MutableLiveData
. Gunakan properti pendukung untuk mengekspos data hanya baca jenisLiveData
. - Di dalam pengontrol UI, ubah jenis data untuk data tersebut menjadi
private
MutableLiveData
. Gunakan properti pendukung untuk mengekspos data hanya baca jenisLiveData
. - Di dalam objek
ViewModel
, ubah jenis data menjadiLiveData
. Gunakan properti pendukung untuk mengekspos data hanya baca jenisLiveData
.
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:
Untuk link ke codelab lain dalam kursus ini, lihat halaman landing codelab Dasar-Dasar Android Kotlin.