Android Kotlin Hakkında Temel Bilgiler 05.2: LiveData ve LiveData gözlemcileri

Bu codelab, Android Kotlin Hakkında Temel Bilgiler kursunun bir parçasıdır. Bu kurstan en iyi şekilde yararlanmak için codelab'leri sırayla tamamlamanızı öneririz. Kursla ilgili tüm codelab'ler Android Kotlin Hakkında Temel Bilgiler codelab'leri açılış sayfasında listelenir.

Giriş

Önceki codelab'de, GuessTheWord uygulamasının verilerinin cihaz yapılandırması değişikliklerinden etkilenmemesi için uygulamada ViewModel kullandınız. Bu codelab'de LiveData ile ViewModel sınıflarındaki verileri nasıl entegre edeceğinizi öğreneceksiniz. Android Mimari Bileşenleri'nden biri olan LiveData, temel veritabanı değiştiğinde görünümleri bilgilendiren veri nesneleri oluşturmanıza olanak tanır.

LiveData sınıfını kullanmak için uygulamanın verilerindeki değişiklikleri gözlemleyen "gözlemciler" (ör. etkinlikler veya parçalar) oluşturursunuz. LiveData yaşam döngüsünün farkındadır. Bu nedenle, yalnızca etkin yaşam döngüsü durumundaki uygulama bileşeni gözlemcilerini günceller.

Bilmeniz gerekenler

  • Kotlin'de temel Android uygulamaları oluşturma
  • Uygulamanızın hedefleri arasında gezinme
  • Etkinlik ve parça yaşam döngüsü.
  • Uygulamanızda ViewModel nesnelerini kullanma
  • ViewModelProvider.Factory arayüzünü kullanarak ViewModel nesneleri oluşturma

Neler öğreneceksiniz?

  • LiveData nesneleri faydalı kılan özellikler.
  • LiveData öğesini ViewModel içinde depolanan verilere ekleme
  • MutableLiveData ne zaman ve nasıl kullanılır?
  • LiveData. içindeki değişiklikleri gözlemlemek için gözlemci yöntemleri ekleme
  • Destekleyici özellik kullanarak LiveData nasıl kapsüllenir?
  • Bir kullanıcı arayüzü denetleyicisi ile karşılık gelen ViewModel arasında nasıl iletişim kurulur?

Yapacaklarınız

  • GuessTheWord uygulamasında kelime ve puan için LiveData kullanın.
  • Kelime veya puan değiştiğinde bunu fark eden gözlemciler ekleyin.
  • Değişen değerleri gösteren metin görünümlerini güncelleyin.
  • Oyunun bitmesi etkinliği eklemek için LiveData gözlemci kalıbını kullanın.
  • Tekrar Oynat düğmesini uygulayın.

5. dersteki codelab'lerde, başlangıç koduyla başlayarak GuessTheWord uygulamasını geliştirirsiniz. GuessTheWord, iki oyuncunun mümkün olan en yüksek puanı elde etmek için işbirliği yaptığı, sessiz sinema tarzı bir oyundur.

Birinci oyuncu, uygulamadaki kelimelere bakar ve her birini sırayla canlandırır. Kelimeyi ikinci oyuncuya göstermemeye dikkat eder. İkinci oyuncu kelimeyi tahmin etmeye çalışır.

Oyunu oynamak için ilk oyuncu cihazda uygulamayı açar ve aşağıdaki ekran görüntüsünde gösterildiği gibi bir kelime (ör. "gitar") görür.

İlk oyuncu, kelimeyi söylememeye dikkat ederek kelimeyi canlandırır.

  • İkinci oyuncu kelimeyi doğru tahmin ettiğinde birinci oyuncu Bildim düğmesine basar. Bu işlem, sayıyı bir artırır ve sonraki kelimeyi gösterir.
  • İkinci oyuncu kelimeyi tahmin edemezse birinci oyuncu Atla düğmesine basar. Bu durumda sayı bir azalır ve bir sonraki kelimeye geçilir.
  • Oyunu sonlandırmak için End Game (Oyunu Sonlandır) düğmesine basın. (Bu işlev, serideki ilk codelab'in başlangıç kodunda yer almaz.)

Bu codelab'de, kullanıcı uygulamadaki tüm kelimeleri tamamladığında oyunu bitirecek bir etkinlik ekleyerek GuessTheWord uygulamasını geliştiriyorsunuz. Ayrıca, kullanıcıların oyunu tekrar oynayabilmesi için puan fragment'ına Tekrar Oyna düğmesi ekliyorsunuz.

Başlık ekranı

Oyun ekranı

Puan ekranı

Bu görevde, bu codelab için başlangıç kodunuzu bulup çalıştıracaksınız. Başlangıç kodu olarak önceki codelab'de oluşturduğunuz GuessTheWord uygulamasını kullanabilir veya bir başlangıç uygulaması indirebilirsiniz.

  1. (İsteğe bağlı) Önceki codelab'deki kodunuzu kullanmıyorsanız bu codelab'in başlangıç kodunu indirin. Kodu açın ve projeyi Android Studio'da açın.
  2. Uygulamayı çalıştırın ve oyunu oynayın.
  3. Atla düğmesinin sonraki kelimeyi gösterdiğini ve puanı bir azalttığını, Anladım düğmesinin ise sonraki kelimeyi gösterdiğini ve puanı bir artırdığını unutmayın. Oyunu Bitir düğmesi oyunu sonlandırır.

LiveData, yaşam döngüsünün farkında olan, gözlemlenebilir bir veri tutucu sınıfıdır. Örneğin, KelimeyiTahminEt uygulamasında mevcut puanın etrafına LiveData sarmalayabilirsiniz. Bu codelab'de LiveData ile ilgili çeşitli özellikleri öğreneceksiniz:

  • LiveData gözlemlenebilir. Bu, LiveData nesnesi tarafından tutulan veriler değiştiğinde bir gözlemciye bildirim gönderildiği anlamına gelir.
  • LiveData verileri tutar; LiveData, herhangi bir veriyle kullanılabilen bir sarmalayıcıdır.
  • LiveData, yaşam döngüsünün farkındadır. Yani yalnızca STARTED veya RESUMED gibi etkin bir yaşam döngüsü durumundaki gözlemcileri günceller.

Bu görevde, LiveData içindeki mevcut puan ve mevcut kelime verilerini GameViewModel öğesine dönüştürerek herhangi bir veri türünü LiveData içine nasıl sarmalayacağınızı öğreneceksiniz. Daha sonraki bir görevde, bu LiveData nesnelerine bir gözlemci ekleyecek ve LiveData nasıl gözlemleyeceğinizi öğreneceksiniz.

1. adım: LiveData'yı kullanmak için puanı ve kelimeyi değiştirin

  1. screens/game paketi altında GameViewModel dosyasını açın.
  2. score ve word değişkenlerinin türünü MutableLiveData olarak değiştirin.

    MutableLiveData, değeri değiştirilebilen bir LiveData'dir. MutableLiveData genel bir sınıftır. Bu nedenle, tuttuğu veri türünü belirtmeniz gerekir.
// The current word
val word = MutableLiveData<String>()
// The current score
val score = MutableLiveData<Int>()
  1. GameViewModel içinde, init bloğunda score ve word değerlerini başlatın. LiveData değişkeninin değerini değiştirmek için değişkende setValue() yöntemini kullanırsınız. Kotlin'de setValue() özelliğini kullanarak value işlevini çağırabilirsiniz.
init {

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

2. adım: LiveData nesne referansını güncelleyin

score ve word değişkenleri artık LiveData türündedir. Bu adımda, value özelliğini kullanarak bu değişkenlere yapılan referansları değiştirirsiniz.

  1. GameViewModel içinde, onSkip() yönteminde score değerini score.value olarak değiştirin. score öğesinin null olabileceğiyle ilgili hataya dikkat edin. Bu hatayı düzeltmeniz gerekir.
  2. Hatayı düzeltmek için onSkip() içinde score.value'ye null işareti ekleyin. Ardından, score üzerinde minus() işlevini çağırın. Bu işlev, null-güvenliği ile çıkarma işlemini gerçekleştirir.
fun onSkip() {
   if (!wordList.isEmpty()) {
       score.value = (score.value)?.minus(1)
   }
   nextWord()
}
  1. onCorrect() yöntemini aynı şekilde güncelleyin: score değişkenine bir null kontrolü ekleyin ve plus() işlevini kullanın.
fun onCorrect() {
   if (!wordList.isEmpty()) {
       score.value = (score.value)?.plus(1)
   }
   nextWord()
}
  1. GameViewModel içinde, nextWord() yönteminde word referansını word.value olarak değiştirin.
private fun nextWord() {
   if (!wordList.isEmpty()) {
       //Select and remove a word from the list
       word.value = wordList.removeAt(0)
   }
}
  1. GameFragment içinde, updateWordText() yönteminde viewModel.word referansını viewModel.word.value. olarak değiştirin.
/** Methods for updating the UI **/
private fun updateWordText() {
   binding.wordText.text = viewModel.word.value
}
  1. GameFragment içinde, updateScoreText() yönteminde, viewModel.score referansını viewModel.score.value. olarak değiştirin.
private fun updateScoreText() {
   binding.scoreText.text = viewModel.score.value.toString()
}
  1. GameFragment içinde, gameFinished() yönteminde viewModel.score referansını viewModel.score.value olarak değiştirin. Gerekli null güvenlik kontrolünü ekleyin.
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. Kodunuzda hata olmadığından emin olun. Uygulamanızı derleyin ve çalıştırın. Uygulamanın işlevselliği, öncekiyle aynı olmalıdır.

Bu görev, puan ve kelime verilerini LiveData nesnelerine dönüştürdüğünüz önceki görevle yakından ilişkilidir. Bu görevde, Observer nesnelerini LiveData nesnelerine ekleyeceksiniz.

  1. GameFragment, içinde, onCreateView() yönteminde, geçerli skor için Observer nesnesini LiveData nesnesine ekleyin, viewModel.score. observe() yöntemini kullanın ve kodu viewModel başlatıldıktan sonra yerleştirin. Kodu basitleştirmek için lambda ifadesi kullanın. (Lambda ifadesi, bildirilmemiş ancak hemen ifade olarak iletilen anonim bir işlevdir.)
viewModel.score.observe(this, Observer { newScore ->
})

Observer referansını çözün. Bunu yapmak için Observer simgesini tıklayın, Alt+Enter tuşuna basın (Mac'te Option+Enter) ve androidx.lifecycle.Observer simgesini içe aktarın.

  1. Yeni oluşturduğunuz gözlemci, gözlemlenen LiveData nesnesinin tuttuğu veriler değiştiğinde bir etkinlik alır. Gözlemcinin içinde, puanı TextView yeni puanla güncelleyin.
/** Setting up LiveData observation relationship **/
viewModel.score.observe(this, Observer { newScore ->
   binding.scoreText.text = newScore.toString()
})
  1. Observer nesnesini geçerli LiveData nesnesine ekleyin. Observer nesnesini geçerli puana eklediğiniz şekilde ekleyin.
/** Setting up LiveData observation relationship **/
viewModel.word.observe(this, Observer { newWord ->
   binding.wordText.text = newWord
})

score veya word değeri değiştiğinde ekranda gösterilen score veya word değeri artık otomatik olarak güncellenir.

  1. GameFragment içinde updateWordText() ve updateScoreText() yöntemlerini ve bunlara yapılan tüm referansları silin. Metin görünümleri LiveData gözlemci yöntemleriyle güncellendiğinden artık bunlara ihtiyacınız yok.
  2. Uygulamanızı çalıştırın. Oyun uygulamanız eskisi gibi çalışmaya devam eder ancak artık LiveData ve LiveData gözlemcilerini kullanır.

Kapsülleme, bir nesnenin bazı alanlarına doğrudan erişimi kısıtlamanın bir yoludur. Bir nesneyi kapsüllediğinizde, özel dahili alanları değiştiren bir dizi herkese açık yöntem kullanıma sunulur. Kapsülleme sayesinde, diğer sınıfların bu dahili alanları nasıl işleyeceğini kontrol edebilirsiniz.

Mevcut kodunuzda, herhangi bir harici sınıf score ve word değişkenlerini value özelliğini kullanarak (ör. viewModel.score.value kullanarak) değiştirebilir. Bu kod laboratuvarında geliştirdiğiniz uygulamada bu durum önemli olmayabilir ancak bir üretim uygulamasında ViewModel nesnelerindeki veriler üzerinde kontrol sahibi olmak istersiniz.

Uygulamanızdaki verileri yalnızca ViewModel düzenlemelidir. Ancak kullanıcı arayüzü denetleyicilerinin verileri okuması gerektiğinden veri alanları tamamen özel olamaz. Uygulamanızın verilerini kapsüllemek için hem MutableLiveData hem de LiveData nesnelerini kullanırsınız.

MutableLiveData - LiveData:

  • MutableLiveData nesnesindeki veriler, adından da anlaşılacağı gibi değiştirilebilir. ViewModel içinde veriler düzenlenebilir olmalıdır. Bu nedenle MutableLiveData kullanılır.
  • LiveData nesnesindeki veriler okunabilir ancak değiştirilemez. ViewModel dışından gelen veriler okunabilir ancak düzenlenemez olmalıdır. Bu nedenle, veriler LiveData olarak sunulmalıdır.

Bu stratejiyi uygulamak için Kotlin backing property'sini kullanırsınız. Destekleyici özellik, tam nesne dışında bir alıcıdan bir şey döndürmenize olanak tanır. Bu görevde, GuessTheWord uygulamasındaki score ve word nesneleri için bir destekleyici özellik uygulayacaksınız.

Puan ve kelimeye destekleyici özellik ekleme

  1. GameViewModel içinde, mevcut score nesnesini private yapın.
  2. Destekleyici özelliklerde kullanılan adlandırma kuralına uymak için score simgesini _score olarak değiştirin. _score özelliği artık dahili olarak kullanılacak, değiştirilebilir oyun puanı sürümüdür.
  3. LiveData türünün score adlı herkese açık bir sürümünü oluşturun.
// The current score
private val _score = MutableLiveData<Int>()
val score: LiveData<Int>
  1. İlk kullanıma hazırlama hatası görüyorsanız. Bu hatanın nedeni, GameFragment içinde score öğesinin LiveData referansı olması ve score öğesinin artık ayarlayıcısına erişememesidir. Kotlin'deki getter ve setter'lar hakkında daha fazla bilgi edinmek için Getter'lar ve Setter'lar başlıklı makaleyi inceleyin.

    Hatayı düzeltmek için GameViewModel içindeki score nesnesinin get() yöntemini geçersiz kılın ve destekleyici özelliği (_score) döndürün.
val score: LiveData<Int>
   get() = _score
  1. GameViewModel içinde, score referanslarını dahili değiştirilebilir sürümü olan _score ile değiştirin.
init {
   ...
   _score.value = 0
   ...
}

...
fun onSkip() {
   if (!wordList.isEmpty()) {
       _score.value = (score.value)?.minus(1)
   }
  ...
}

fun onCorrect() {
   if (!wordList.isEmpty()) {
       _score.value = (score.value)?.plus(1)
   }
   ...
}
  1. word nesnesini _word olarak yeniden adlandırın ve score nesnesinde yaptığınız gibi bu nesne için bir destekleyici özellik ekleyin.
// 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)
   }
}

Tebrikler, LiveData nesnelerini word ve score kapsüllediniz.

Mevcut uygulamanızda kullanıcı Oyunu Bitir düğmesine dokunduğunda skor ekranına gidiliyor. Ayrıca, oyuncular tüm kelimeleri tamamladığında uygulamanın puan ekranına gitmesini istiyorsunuz. Oyuncular son kelimeyi tamamladıktan sonra oyunun otomatik olarak sona ermesini istiyorsunuz. Böylece kullanıcının düğmeye dokunması gerekmez.

Bu işlevselliği uygulamak için tüm kelimeler gösterildiğinde ViewModel tarafından tetiklenen ve parçaya iletilen bir etkinlik gerekir. Bunu yapmak için LiveData observer kalıbını kullanarak oyunun bitmesi etkinliğini modellendirirsiniz.

Gözlemci modeli

Gözlemci kalıbı, bir yazılım tasarım kalıbıdır. Nesneler arasındaki iletişimi belirtir: gözlemlenebilir (gözlemin "öznesi") ve gözlemciler. Gözlemlenebilir, durumundaki değişiklikler hakkında gözlemcileri bilgilendiren bir nesnedir.

Bu uygulamadaki LiveData örneğinde, gözlemlenebilir (özne) LiveData nesnesidir ve gözlemciler, kullanıcı arayüzü denetleyicilerindeki (ör. parçalar) yöntemlerdir. LiveData içinde sarmalanmış veriler her değiştiğinde durum değişikliği gerçekleşir. LiveData sınıfları, ViewModel ile fragment arasında iletişim kurmak için çok önemlidir.

1. adım: Maçın bitmesi etkinliğini algılamak için LiveData'yı kullanın

Bu görevde, oyunun bitmesi etkinliğini modellemek için LiveData gözlemci kalıbını kullanıyorsunuz.

  1. GameViewModel içinde _eventGameFinish adlı bir Boolean MutableLiveData nesnesi oluşturun. Bu nesne, biten maç etkinliğini barındırır.
  2. _eventGameFinish nesnesini başlattıktan sonra eventGameFinish adlı bir destekleyici özellik oluşturup başlatın.
// Event which triggers the end of the game
private val _eventGameFinish = MutableLiveData<Boolean>()
val eventGameFinish: LiveData<Boolean>
   get() = _eventGameFinish
  1. GameViewModel bölümünde bir onGameFinish() yöntemi ekleyin. Yöntemde, oyunun bitiş etkinliği olan eventGameFinish'yi true olarak ayarlayın.
/** Method for the game completed event **/
fun onGameFinish() {
   _eventGameFinish.value = true
}
  1. GameViewModel içinde, nextWord() yönteminde kelime listesi boşsa oyunu sonlandırın.
private fun nextWord() {
   if (wordList.isEmpty()) {
       onGameFinish()
   } else {
       //Select and remove a _word from the list
       _word.value = wordList.removeAt(0)
   }
}
  1. GameFragment içinde, onCreateView() içinde, viewModel başlatıldıktan sonra eventGameFinish'ye bir gözlemci ekleyin. observe() yöntemini kullanın. Lambda işlevinin içinde gameFinished() yöntemini çağırın.
// Observer for the Game finished event
viewModel.eventGameFinish.observe(this, Observer<Boolean> { hasFinished ->
   if (hasFinished) gameFinished()
})
  1. Uygulamanızı çalıştırın, oyunu oynayın ve tüm kelimeleri inceleyin. Uygulama, Oyunu Bitir'e dokunana kadar oyun parçasında kalmak yerine otomatik olarak skor ekranına gider.

    Kelime listesi boşaldıktan sonra eventGameFinish ayarlanır, oyun parçasındaki ilişkili gözlemci yöntemi çağrılır ve uygulama ekran parçasına gider.
  2. Eklediğiniz kod, yaşam döngüsü sorunu oluşturuyor. Sorunu anlamak için GameFragment sınıfında, gameFinished() yöntemindeki gezinme kodunu yorum satırı yapın. Toast mesajını yöntemde tuttuğunuzdan emin olun.
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. Uygulamanızı çalıştırın, oyunu oynayın ve tüm kelimeleri inceleyin. Oyun ekranının alt kısmında kısa süreliğine "Oyun yeni bitti" yazan bir kısa mesaj bildirimi gösterilir. Bu, beklenen bir davranıştır.

Şimdi cihazı veya emülatörü döndürün. Bildirim tekrar gösterilir. Cihazı birkaç kez daha döndürdüğünüzde, bildirim büyük olasılıkla her seferinde gösterilir. Bu bir hatadır. Çünkü pop-up, yalnızca oyun bittiğinde bir kez gösterilmelidir. Toast, parça her yeniden oluşturulduğunda gösterilmemelidir. Bu sorunu bir sonraki görevde çözeceksiniz.

2. adım: Tamamlanan oyun etkinliğini sıfırlayın

LiveData, genellikle yalnızca veriler değiştiğinde gözlemcilere güncellemeler gönderir. Bu davranışın istisnası, gözlemcinin etkin olmayan durumdan etkin duruma geçmesi durumunda gözlemcilerin de güncellemeleri almasıdır.

Bu nedenle, uygulamanızda oyunun tamamlandığına dair bildirim tekrar tekrar tetikleniyor. Oyun parçası, ekran döndürüldükten sonra yeniden oluşturulduğunda etkin olmayan durumdan etkin duruma geçiyor. Parçadaki gözlemci, mevcut ViewModel öğesine yeniden bağlanır ve mevcut verileri alır. gameFinished() yöntemi yeniden tetiklenir ve kısa mesaj gösterilir.

Bu görevde, GameViewModel içinde eventGameFinish işaretini sıfırlayarak bu sorunu düzeltip pop-up'ı yalnızca bir kez gösteriyorsunuz.

  1. GameViewModel içinde, oyunun bitiş etkinliğini sıfırlamak için onGameFinishComplete() yöntemi ekleyin _eventGameFinish.
/** Method for the game completed event **/

fun onGameFinishComplete() {
   _eventGameFinish.value = false
}
  1. GameFragment içinde, gameFinished() sonunda viewModel nesnesinde onGameFinishComplete() işlevini çağırın. (Şimdilik gezinme kodunu gameFinished() yorum satırı olarak bırakın.)
private fun gameFinished() {
   ...
   viewModel.onGameFinishComplete()
}
  1. Uygulamayı çalıştırın ve oyunu oynayın. Tüm kelimeleri okuyun, ardından cihazın ekran yönünü değiştirin. Bildirim yalnızca bir kez gösterilir.
  2. GameFragment içinde, gameFinished() yönteminde gezinme kodunun yorumunu kaldırın.

    Android Studio'da yorumu kaldırmak için yorum satırlarını seçip Control+/ tuşuna (Mac'te Command+/) basın.
private fun gameFinished() {
   Toast.makeText(activity, "Game has just finished", Toast.LENGTH_SHORT).show()
   val action = GameFragmentDirections.actionGameToScore()
   action.score = viewModel.score.value?:0
   findNavController(this).navigate(action)
   viewModel.onGameFinishComplete()
}

Android Studio tarafından istenirse androidx.navigation.fragment.NavHostFragment.findNavController içe aktarın.

  1. Uygulamayı çalıştırın ve oyunu oynayın. Tüm kelimeleri tamamladıktan sonra uygulamanın otomatik olarak nihai puan ekranına yönlendirdiğinden emin olun.

Mükemmel! Uygulamanız, kelime listesinin boş olduğunu GameViewModel'den oyun parçasına iletmek için LiveData kullanarak oyunun bittiği etkinliğini tetikliyor. Oyun parçası daha sonra puan parçasına gider.

Bu görevde, ScoreViewModel içinde puanı LiveData nesnesine değiştirip gözlemci ekleyeceksiniz. Bu görev, LiveData öğesini GameViewModel öğesine eklerken yaptığınız işleme benzer.

Bu değişiklikleri, uygulamanızdaki tüm verilerin LiveData kullanması için ScoreViewModel'da eksiksiz olarak yaparsınız.

  1. ScoreViewModel bölümünde, score değişken türünü MutableLiveData olarak değiştirin. _score olarak yeniden adlandırın ve destekleyici bir özellik ekleyin.
private val _score = MutableLiveData<Int>()
val score: LiveData<Int>
   get() = _score
  1. ScoreViewModel içinde, init bloğunda _score öğesini başlatın. İstediğiniz zaman init bloğundaki girişi kaldırabilir veya girişten çıkabilirsiniz.
init {
   _score.value = finalScore
}
  1. ScoreFragment içinde, onCreateView() içinde, viewModel başlatıldıktan sonra LiveData puan nesnesi için bir gözlemci ekleyin. Lambda ifadesinin içinde puan değerini puan metni görünümüne ayarlayın. Metin görünümünü doğrudan puan değeriyle atayan kodu ViewModel öğesinden kaldırın.

Eklenecek kod:

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

Kaldırılacak kod:

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

Android Studio tarafından istendiğinde androidx.lifecycle.Observer dosyasını içe aktarın.

  1. Uygulamanızı çalıştırın ve oyunu oynayın. Uygulama eskisi gibi çalışmaya devam eder ancak artık puanı güncellemek için LiveData ve bir gözlemci kullanır.

Bu görevde, skor ekranına bir Tekrar Oyna düğmesi ekleyip LiveData etkinliğini kullanarak tıklama işleyicisini uygulayacaksınız. Düğme, puan ekranından oyun ekranına gitmek için bir etkinliği tetikler.

Uygulamanın başlangıç kodunda Tekrar Oyna düğmesi bulunur ancak bu düğme gizlidir.

  1. res/layout/score_fragment.xml bölümündeki play_again_button düğmesi için visibility özelliğinin değerini visible olarak değiştirin.
<Button
   android:id="@+id/play_again_button"
...
   android:visibility="visible"
 />
  1. ScoreViewModel içinde, _eventPlayAgain adlı bir Boolean tutacak LiveData nesnesi ekleyin. Bu nesne, skor ekranından oyun ekranına gitmek için LiveData etkinliğini kaydetmek üzere kullanılır.
private val _eventPlayAgain = MutableLiveData<Boolean>()
val eventPlayAgain: LiveData<Boolean>
   get() = _eventPlayAgain
  1. ScoreViewModel içinde, etkinliği ayarlama ve sıfırlama yöntemlerini tanımlayın (_eventPlayAgain).
fun onPlayAgain() {
   _eventPlayAgain.value = true
}
fun onPlayAgainComplete() {
   _eventPlayAgain.value = false
}
  1. ScoreFragment içinde eventPlayAgain için bir gözlemci ekleyin. Kodu onCreateView() ifadesinin sonuna, return ifadesinden önce yerleştirin. Lambda ifadesinin içinde oyun ekranına geri dönün ve eventPlayAgain değerini sıfırlayın.
// Navigates back to game when button is pressed
viewModel.eventPlayAgain.observe(this, Observer { playAgain ->
   if (playAgain) {
      findNavController().navigate(ScoreFragmentDirections.actionRestart())
       viewModel.onPlayAgainComplete()
   }
})

Android Studio tarafından istendiğinde androidx.navigation.fragment.findNavController içe aktarın.

  1. ScoreFragment içinde, onCreateView() içinde PlayAgain düğmesine bir tıklama dinleyicisi ekleyin ve viewModel.onPlayAgain() işlevini çağırın.
binding.playAgainButton.setOnClickListener {  viewModel.onPlayAgain()  }
  1. Uygulamanızı çalıştırın ve oyunu oynayın. Oyun bittiğinde skor ekranında son skor ve Tekrar Oyna düğmesi gösterilir. PlayAgain düğmesine dokunduğunuzda uygulama, oyunu tekrar oynayabilmeniz için oyun ekranına yönlendirir.

Tebrikler! Uygulamanızın mimarisini LiveData nesnelerini ViewModel içinde kullanacak şekilde değiştirdiniz ve LiveData nesnelerine gözlemciler eklediniz. LiveData, LiveData tarafından tutulan değer değiştiğinde gözlemci nesneleri bilgilendirir.

Android Studio projesi: GuessTheWord

LiveData

  • LiveData, yaşam döngüsünün farkında olan, gözlemlenebilir bir veri tutucu sınıfıdır ve Android Architecture Components'ın bir parçasıdır.
  • Veriler güncellendiğinde kullanıcı arayüzünüzün otomatik olarak güncellenmesini sağlamak için LiveData kullanabilirsiniz.
  • LiveData gözlemlenebilir. Bu, etkinlik veya parça gibi bir gözlemcinin, LiveData nesnesi tarafından tutulan veriler değiştiğinde bilgilendirilebileceği anlamına gelir.
  • LiveData, verileri tutar ve herhangi bir veriyle kullanılabilen bir sarmalayıcıdır.
  • LiveData, yaşam döngüsünün farkındadır. Yani yalnızca STARTED veya RESUMED gibi etkin bir yaşam döngüsü durumundaki gözlemcileri günceller.

LiveData eklemek için

  • ViewModel içindeki veri değişkenlerinin türünü LiveData veya MutableLiveData olarak değiştirin.

MutableLiveData, değeri değiştirilebilen bir LiveData nesnesidir. MutableLiveData genel bir sınıftır. Bu nedenle, tuttuğu veri türünü belirtmeniz gerekir.

  • LiveData tarafından tutulan verilerin değerini değiştirmek için LiveData değişkeninde setValue() yöntemini kullanın.

LiveData'yı kapsüllemek için

  • ViewModel içindeki LiveData düzenlenebilir olmalıdır. ViewModel dışında LiveData okunabilir olmalıdır. Bu, Kotlin backing property kullanılarak uygulanabilir.
  • Kotlin destekleyici özelliği, getter'dan tam nesne dışında bir şey döndürmenize olanak tanır.
  • LiveData öğesini kapsüllemek için ViewModel içinde private MutableLiveData öğesini kullanın ve ViewModel dışında bir LiveData destek özelliği döndürün.

Observable LiveData

  • LiveData, gözlemci kalıbını izler. "Gözlemlenebilir" olan LiveData nesnesidir ve gözlemciler, kullanıcı arayüzü denetleyicilerindeki (ör. parçalar) yöntemlerdir. LiveData içine yerleştirilmiş veriler her değiştiğinde kullanıcı arayüzü denetleyicilerindeki gözlemci yöntemleri bilgilendirilir.
  • LiveData öğesini gözlemlenebilir hale getirmek için observe() yöntemini kullanarak gözlemcilerdeki (etkinlikler ve parçalar gibi) LiveData referansına bir gözlemci nesnesi ekleyin.
  • Bu LiveData gözlemci deseni, ViewModel ile kullanıcı arayüzü denetleyicileri arasında iletişim kurmak için kullanılabilir.

Udacity kursu:

Android geliştirici belgeleri:

Diğer:

Bu bölümde, bir eğitmenin yönettiği kurs kapsamında bu codelab'i tamamlayan öğrenciler için olası ödevler listelenmektedir. Eğitmen, aşağıdakileri yapmalıdır:

  • Gerekirse ödev atayın.
  • Öğrencilere ev ödevi ödevlerini nasıl göndereceklerini bildirin.
  • Ödevlere not verin.

Eğitmenler bu önerileri istedikleri kadar kullanabilir ve uygun olduğunu düşündükleri diğer ödevleri verebilirler.

Bu codelab'i kendi başınıza tamamlıyorsanız bilginizi test etmek için bu ödevleri kullanabilirsiniz.

Bu soruları yanıtlayın

1. Soru

LiveData verilerini ViewModel içinde nasıl kapsarsınız? Böylece harici nesneler, verileri güncelleyemeden okuyabilir.

  • ViewModel nesnesinde, verilerin veri türünü private LiveData olarak değiştirin. MutableLiveData türündeki salt okunur verileri göstermek için bir destekleyici özellik kullanın.
  • ViewModel nesnesinde, verilerin veri türünü private MutableLiveData olarak değiştirin. LiveData türündeki salt okunur verileri göstermek için bir destekleyici özellik kullanın.
  • Kullanıcı arayüzü denetleyicisinde verilerin veri türünü private MutableLiveData olarak değiştirin. LiveData türündeki salt okunur verileri göstermek için bir destekleyici özellik kullanın.
  • ViewModel nesnesinin içinde, verilerin veri türünü LiveData olarak değiştirin. LiveData türündeki salt okunur verileri göstermek için bir destekleyici özellik kullanın.

2. Soru

LiveData, kullanıcı arayüzü denetleyicisi aşağıdaki durumlardan hangisindeyse kullanıcı arayüzü denetleyicisini (ör. bir parça) günceller?

  • Devam ettirildi
  • Arka planda
  • Duraklatıldı
  • Durduruldu

3. Soru

LiveData gözlemci kalıbında, gözlemlenebilir öğe (gözlemlenen öğe) nedir?

  • Gözlemci yöntemi
  • LiveData nesnesindeki veriler
  • Kullanıcı arayüzü denetleyicisi
  • ViewModel nesnesi

Bir sonraki derse başlayın: 5.3: ViewModel ve LiveData ile veri bağlama

Bu kurstaki diğer codelab'lerin bağlantılarını Android Kotlin Hakkında Temel Bilgiler codelab'leri açılış sayfasında bulabilirsiniz.