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 antarmukaViewModelProvider.Factory
.
Yang akan Anda pelajari
- Apa yang membuat objek
LiveData
berguna. - Cara menambahkan
LiveData
ke data yang disimpan diViewModel
. - 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.
- (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.
- 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 objekLiveData
berubah.LiveData
menyimpan data;LiveData
adalah wrapper yang dapat digunakan dengan data apa punLiveData
berbasis siklus proses, yang berarti hanya memperbarui observer yang ada dalam status siklus proses aktif sepertiSTARTED
atauRESUMED
.
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
- Pada 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 menjadi jenis LiveData
. Pada langkah ini, Anda mengubah referensi ke variabel tersebut, menggunakan properti value
.
- Di
GameViewModel
, di metodeonSkip()
, ubahscore
menjadiscore.value
. Perhatikan error tentangscore
yang mungkin adalahnull
. Anda akan memperbaiki error ini berikutnya. - Untuk mengatasi error, tambahkan pemeriksaan
null
kescore.value
dalamonSkip()
. 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
, di 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 referensi menjadiviewModel
.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 referensi menjadiviewModel
.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. 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.
- Di
GameFragment,
dalam metodeonCreateView()
, lampirkan objekObserver
ke objekLiveData
untuk skor saat ini,viewModel.score
. Gunakan metodeobserve()
dan masukkan 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), dan impor androidx.lifecycle.Observer
.
- Observer yang baru saja Anda buat akan menerima peristiwa bila data yang dimiliki oleh 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
saat ini. Lakukan dengan cara yang sama seperti saat 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()
, dan semua referensi ke dalamnya. Anda tidak memerlukannya lagi, karena tampilan teks diperbarui oleh metode observerLiveData
. - Jalankan aplikasi Anda. Aplikasi game Anda seharusnya bekerja persis seperti sebelumnya, tetapi sekarang aplikasi ini menggunakan observer
LiveData
danLiveData
.
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 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 menerapkan properti pendukung untuk objek score
dan word
di aplikasi GuessTheWord.
Menambahkan properti pendukung ke skor dan kata
- Di
GameViewModel
, buat objekscore
saat iniprivate
. - 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. - 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 penyetelnya. Untuk mempelajari pengambil dan penyetel di Kotlin lebih lanjut, lihat Pengambil dan Penyetel.
Untuk mengatasi error, ganti metodeget()
untuk objekscore
diGameViewModel
dan tampilkan properti pendukung,_score
.
val score: LiveData<Int>
get() = _score
- Di
GameViewModel
, ubah referensiscore
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)
}
...
}
- Ganti nama objek
word
menjadi_word
dan tambahkan properti pendukung untuk objek tersebut, 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, 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.
- Di
GameViewModel
, buat objekBoolean
MutableLiveData
bernama_eventGameFinish
. Objek ini akan menyimpan peristiwa yang sudah diselesaikan game. - 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, tetapkan peristiwa yang sudah selesai game,eventGameFinish
, ketrue
.
/** Method for the game completed event **/
fun onGameFinish() {
_eventGameFinish.value = true
}
- Di
GameViewModel
, di 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, 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. - Kode yang Anda tambahkan telah memperkenalkan masalah siklus proses. Untuk memahami masalah ini, jadikan kode navigasi dalam metode
gameFinished()
sebagai komentar di classGameFragment
. Pastikan untuk mempertahankan pesanToast
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)
}
- 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
.
- Di
GameViewModel
, tambahkan metodeonGameFinishComplete()
untuk mereset acara yang telah selesai,_eventGameFinish
.
/** Method for the game completed event **/
fun onGameFinishComplete() {
_eventGameFinish.value = false
}
- Di
GameFragment
, di akhirgameFinished()
, panggilonGameFinishComplete()
pada objekviewModel
. (Biarkan kode navigasi digameFinished()
dikomentari untuk saat ini.)
private fun gameFinished() {
...
viewModel.onGameFinishComplete()
}
- Jalankan aplikasi dan mainkan game. Periksa semua kata, lalu ubah orientasi layar perangkat. Toast hanya ditampilkan sekali.
- Di
GameFragment
, dalam metodegameFinished()
, hapus tanda komentar kode navigasi.
Untuk menghapus tanda komentar di Android Studio, pilih baris yang diberi komentar, lalu 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. 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
.
- Di
ScoreViewModel
, ubah jenis variabelscore
menjadiMutableLiveData
. Ganti namanya menurut 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 langsung menetapkan tampilan teks dengan nilai skor dariViewModel
.
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
.
- 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.
- 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
untuk membuka layar skor ke layar game.
private val _eventPlayAgain = MutableLiveData<Boolean>()
val eventPlayAgain: LiveData<Boolean>
get() = _eventPlayAgain
- Di
ScoreViewModel
, tentukan metode untuk menetapkan dan mereset peristiwa,_eventPlayAgain
.
fun onPlayAgain() {
_eventPlayAgain.value = true
}
fun onPlayAgainComplete() {
_eventPlayAgain.value = false
}
- Di
ScoreFragment
, tambahkan pengamat untukeventPlayAgain
. Masukkan 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 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 objekLiveData
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 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 diobservasi
LiveData
mengikuti pola pengamat. "observable" adalah objekLiveData
, dan pengamat adalah metode dalam pengontrol UI, seperti fragmen. Setiap kali data yang digabungkan dalamLiveData
berubah, metode pengamat di pengontrol UI akan diberi tahu.- Agar
LiveData
dapat diamati, lampirkan objek observer ke referensiLiveData
dalam observer (seperti aktivitas dan fragmen) menggunakan metodeobserve()
. - Pola pengamat
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. 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 menjadiprivate
LiveData
. Gunakan properti backing untuk mengekspos data hanya baca jenisMutableLiveData
. - Di dalam objek
ViewModel
, ubah jenis data data menjadiprivate
MutableLiveData
. Gunakan properti backing untuk mengekspos data hanya baca jenisLiveData
. - Di dalam pengontrol UI, ubah jenis data data menjadi
private
MutableLiveData
. Gunakan properti backing untuk mengekspos data hanya baca jenisLiveData
. - Di dalam objek
ViewModel
, ubah jenis data data menjadiLiveData
. Gunakan properti backing untuk mengekspos data hanya baca jenisLiveData
.
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:
Untuk link ke codelab lainnya dalam kursus ini, lihat halaman landing codelab Dasar-Dasar Kotlin Android.