Android Kotlin Hakkında Temel Bilgiler 07.2: RecyclerView ile DiffUtil ve veri bağlama

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 TrackMySleepQuality uygulamasını, uyku kalitesiyle ilgili verileri RecyclerView içinde gösterecek şekilde güncellemiştiniz. İlk RecyclerView'nizi oluştururken öğrendiğiniz teknikler, çok büyük olmayan basit listeler gösteren çoğu RecyclerViews için yeterlidir. Ancak, RecyclerView'yı büyük listeler için daha verimli hale getiren ve kodunuzun karmaşık listeler ve ızgaralar için bakımını ve genişletilmesini kolaylaştıran bir dizi teknik vardır.

Bu codelab'de, önceki codelab'deki uyku izleme uygulamasını temel alacaksınız. Uyku verileri listesini güncellemenin daha etkili bir yolunu ve RecyclerView ile veri bağlamayı nasıl kullanacağınızı öğrenirsiniz. (Önceki codelab'den uygulamayı kullanmıyorsanız bu codelab'in başlangıç kodunu indirebilirsiniz.)

Bilmeniz gerekenler

  • Etkinlik, parçalar ve görünümler kullanarak temel bir kullanıcı arayüzü oluşturma.
  • Parçalar arasında gezinme ve parçalar arasında veri aktarmak için safeArgs kullanma.
  • Modelleri, model fabrikalarını, dönüşümleri ve LiveData ile gözlemcilerini görüntüleyin.
  • Room veritabanı oluşturma, DAO oluşturma ve varlıkları tanımlama
  • Veritabanı ve diğer uzun süren görevler için eş yordamları kullanma
  • Adapter, ViewHolder ve öğe düzeniyle temel bir RecyclerView nasıl uygulanır?

Neler öğreneceksiniz?

  • DiffUtil kullanarak RecyclerView tarafından gösterilen bir listeyi nasıl verimli bir şekilde güncelleyebilirsiniz?
  • RecyclerView ile veri bağlamayı kullanma
  • Verileri dönüştürmek için bağlama adaptörlerini kullanma

Yapacaklarınız

  • Bu serideki önceki codelab'de yer alan TrackMySleepQuality uygulamasını temel alın.
  • DiffUtil kullanarak listeyi verimli bir şekilde güncellemek için SleepNightAdapter simgesini güncelleyin.
  • Verileri dönüştürmek için bağlama adaptörlerini kullanarak RecyclerView için veri bağlamayı uygulayın.

Uyku izleme uygulamasının, aşağıdaki şekilde gösterildiği gibi parçalarla temsil edilen iki ekranı vardır.

Solda gösterilen ilk ekranda izlemeyi başlatma ve durdurma düğmeleri bulunur. Ekranda kullanıcının uyku verilerinden bazıları gösterilir. Temizle düğmesi, uygulamanın kullanıcı için topladığı tüm verileri kalıcı olarak siler. Sağda gösterilen ikinci ekranda uyku kalitesi derecesi seçilir.

Bu uygulama, uyku verilerini kalıcı hale getirmek için kullanıcı arayüzü denetleyicisi, ViewModel ve LiveData ile Room veritabanı kullanacak şekilde tasarlanmıştır.

Uyku verileri RecyclerView olarak gösterilir. Bu codelab'de, DiffUtil ve RecyclerView için veri bağlama bölümünü oluşturacaksınız. Bu codelab'den sonra uygulamanızın görünümü değişmeyecek ancak daha verimli, ölçeklendirmesi ve bakımı daha kolay olacak.

Önceki codelab'deki SleepTracker uygulamasını kullanmaya devam edebilir veya GitHub'dan RecyclerViewDiffUtilDataBinding-Starter uygulamasını indirebilirsiniz.

  1. Gerekirse GitHub'dan RecyclerViewDiffUtilDataBinding-Starter uygulamasını indirip projeyi Android Studio'da açın.
  2. Uygulamayı çalıştırın.
  3. SleepNightAdapter.kt dosyasını açın.
  4. Uygulamanın yapısını öğrenmek için kodu inceleyin. Kullanıcıya uyku verilerini göstermek üzere bağdaştırıcı deseniyle RecyclerView kullanmanın özeti için aşağıdaki şemaya bakın.

  • Uygulama, kullanıcı girişinden SleepNight nesnelerin listesini oluşturur. Her SleepNight nesnesi, tek bir gece uykusunu, süresini ve kalitesini temsil eder.
  • SleepNightAdapter, SleepNight nesnelerinin listesini RecyclerView tarafından kullanılabilecek ve görüntülenebilecek bir şeye dönüştürür.
  • SleepNightAdapter bağdaştırıcısı, verileri görüntülemek için geri dönüşüm görünümünün görünümlerini, verilerini ve meta bilgilerini içeren ViewHolders oluşturur.
  • RecyclerView, görüntülenecek öğe sayısını belirlemek için SleepNightAdapter kullanır (getItemCount()). RecyclerView, görüntüleme tutucuları görüntüleme için verilere bağlamak üzere onCreateViewHolder() ve onBindViewHolder() kullanır.

notifyDataSetChanged() yöntemi verimsizdir

Listedeki bir öğenin değiştiğini ve güncellenmesi gerektiğini RecyclerView öğesine bildirmek için mevcut kod, aşağıdaki örnekte gösterildiği gibi SleepNightAdapter içinde notifyDataSetChanged() öğesini çağırır.

var data =  listOf<SleepNight>()
   set(value) {
       field = value
       notifyDataSetChanged()
   }

Ancak notifyDataSetChanged(), RecyclerView'ye listenin tamamının geçersiz olabileceğini bildirir. Sonuç olarak, RecyclerView ekranda görünür olmayan öğeler de dahil olmak üzere listedeki her öğeyi yeniden bağlar ve yeniden çizer. Bu, çok fazla gereksiz işe yol açar. Büyük veya karmaşık listelerde bu işlem, kullanıcının listede gezinirken ekranın titremesine veya takılmasına neden olacak kadar uzun sürebilir.

Bu sorunu düzeltmek için RecyclerView'a tam olarak neyin değiştiğini söyleyebilirsiniz. RecyclerView daha sonra ekranda değişen görünümleri güncelleyebilir.

RecyclerView, tek bir öğeyi güncellemek için zengin bir API'ye sahiptir. notifyItemChanged() işlevini kullanarak RecyclerView'a bir öğenin değiştiğini bildirebilirsiniz. Eklenen, kaldırılan veya taşınan öğeler için de benzer işlevler kullanabilirsiniz. Bu işlemleri manuel olarak da yapabilirsiniz ancak bu görev kolay olmayacak ve oldukça fazla kod içerebilir.

Neyse ki daha iyi bir yol var.

DiffUtil verimlidir ve zorlu işleri sizin için yapar.

RecyclerView, iki liste arasındaki farkları hesaplamak için kullanılan DiffUtil adlı bir sınıfa sahiptir. DiffUtil, eski ve yeni listeyi alıp aradaki farkı bulur. Eklenen, kaldırılan veya değiştirilen öğeleri bulur. Daha sonra Eugene W. Myers'ın fark algoritması kullanılarak eski listeden yeni listeyi oluşturmak için yapılması gereken minimum değişiklik sayısı belirlenir.

DiffUtil, neyin değiştiğini anladıktan sonra RecyclerView bu bilgileri yalnızca değiştirilen, eklenen, kaldırılan veya taşınan öğeleri güncellemek için kullanabilir. Bu, listenin tamamını yeniden yapmaktan çok daha verimlidir.

Bu görevde, SleepNightAdapter öğesini DiffUtil kullanarak RecyclerView öğesini verilerdeki değişikliklere göre optimize edecek şekilde yükseltiyorsunuz.

1. adım: SleepNightDiffCallback'i uygulayın

DiffUtil sınıfının işlevlerini kullanmak için DiffUtil.ItemCallback sınıfını genişletin.

  1. SleepNightAdapter.kt adlı kişiyi aç.
  2. SleepNightAdapter için tam sınıf tanımının altında, DiffUtil.ItemCallback'yi genişleten SleepNightDiffCallback adlı yeni bir üst düzey sınıf oluşturun. SleepNight öğesini genel bir parametre olarak iletin.
class SleepNightDiffCallback : DiffUtil.ItemCallback<SleepNight>() {
}
  1. İmleci SleepNightDiffCallback sınıf adının içine yerleştirin.
  2. Alt+Enter (Mac'te Option+Enter ) tuşuna basın ve Implement Members'ı (Üyeleri Uygula) seçin.
  3. Açılan iletişim kutusunda, areItemsTheSame() ve areContentsTheSame() yöntemlerini seçmek için sol tıklarken Shift tuşunu basılı tutun, ardından Tamam'ı tıklayın.

    Bu işlem, aşağıdaki örnekte gösterildiği gibi iki yöntem için SleepNightDiffCallback içinde saplar oluşturur. DiffUtil, listenin ve öğelerin nasıl değiştiğini anlamak için bu iki yöntemi kullanır.
    override fun areItemsTheSame(oldItem: SleepNight, newItem: SleepNight): Boolean {
        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
    }

    override fun areContentsTheSame(oldItem: SleepNight, newItem: SleepNight): Boolean {
        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
    }
  1. areItemsTheSame() içinde, TODO yerine, iletilen iki SleepNight öğenin (oldItem ve newItem) aynı olup olmadığını test eden kodu girin. Öğelerin nightId değeri aynıysa aynı öğe oldukları için true değerini döndürün. Aksi takdirde false değerini döndürür. DiffUtil, bir öğenin eklenip eklenmediğini, kaldırılıp kaldırılmadığını veya taşınıp taşınmadığını belirlemek için bu testi kullanır.
override fun areItemsTheSame(oldItem: SleepNight, newItem: SleepNight): Boolean {
   return oldItem.nightId == newItem.nightId
}
  1. areContentsTheSame() içinde oldItem ve newItem'nin aynı verileri içerip içermediğini, yani eşit olup olmadığını kontrol edin. Bu eşitlik kontrolü, SleepNight bir veri sınıfı olduğundan tüm alanları kontrol eder. Data sınıfları, equals ve birkaç başka yöntemi sizin için otomatik olarak tanımlar. oldItem ve newItem arasında farklılıklar varsa bu kod, DiffUtil öğesinin güncellendiğini bildirir.
override fun areContentsTheSame(oldItem: SleepNight, newItem: SleepNight): Boolean {
   return oldItem == newItem
}

Değişen bir listeyi görüntülemek için RecyclerView kullanmak yaygın bir yöntemdir. RecyclerView, liste destekli bir RecyclerView bağdaştırıcısı oluşturmanıza yardımcı olan bir bağdaştırıcı sınıfı (ListAdapter) sağlar.

ListAdapter, liste için izleme yapar ve liste güncellendiğinde bağdaştırıcıyı bilgilendirir.

1. adım: Adaptörünüzü ListAdapter'ı genişletecek şekilde değiştirin

  1. SleepNightAdapter.kt dosyasında, SleepNightAdapter sınıfının imzasını ListAdapter'yi genişletecek şekilde değiştirin.
  2. İstenirse androidx.recyclerview.widget.ListAdapter dosyasını içe aktarın.
  3. SleepNight değerini, SleepNightAdapter.ViewHolder değerinden önce ListAdapter işlevine ilk bağımsız değişken olarak ekleyin.
  4. SleepNightDiffCallback() öğesini oluşturucuya parametre olarak ekleyin. ListAdapter, listede neyin değiştiğini anlamak için bunu kullanır. Tamamlanmış SleepNightAdapter sınıf imzanız aşağıdaki gibi görünmelidir.
class SleepNightAdapter : ListAdapter<SleepNight, SleepNightAdapter.ViewHolder>(SleepNightDiffCallback()) {
  1. SleepNightAdapter sınıfının içinde, ayarlayıcı da dahil olmak üzere data alanını silin. ListAdapter, liste takibini sizin için yaptığından artık bu listeye ihtiyacınız yoktur.
  2. getItemCount() geçersiz kılmasını silin. Çünkü ListAdapter bu yöntemi sizin için uygular.
  3. onBindViewHolder() içindeki hatayı düzeltmek için item değişkenini değiştirin. item almak için data kullanmak yerine ListAdapter tarafından sağlanan getItem(position) yöntemini çağırın.
val item = getItem(position)

2. adım: Listeyi güncel tutmak için submitList() işlevini kullanın

Kodunuz, değiştirilmiş bir liste olduğunda ListAdapter'ya bilgi vermelidir. ListAdapter, listenin yeni bir sürümünün kullanıma sunulduğunu ListAdapter'ya bildirmek için submitList() adlı bir yöntem sağlar. Bu yöntem çağrıldığında ListAdapter, yeni listeyi eski listeyle karşılaştırır ve eklenen, kaldırılan, taşınan veya değiştirilen öğeleri algılar. Ardından ListAdapter, RecyclerView tarafından gösterilen öğeleri günceller.

  1. SleepTrackerFragment.kt adlı kişiyi aç.
  2. onCreateView() içinde, sleepTrackerViewModel üzerindeki gözlemcide, sildiğiniz data değişkenine referans verilen hatayı bulun.
  3. adapter.data = it yerine adapter.submitList(it) ile görüşme isteği gönderin. Güncellenen kod aşağıda gösterilmektedir.

sleepTrackerViewModel.nights.observe(viewLifecycleOwner, Observer {
   it?.let {
       adapter.submitList(it)
   }
})
  1. Uygulamanızı çalıştırın. Uygulamanız daha hızlı çalışır. Listeniz küçükse bu hız farkı fark edilmeyebilir.

Bu görevde, veri bağlamayı ayarlamak için önceki codelab'lerdekiyle aynı tekniği kullanacak ve findViewById() çağrılarını ortadan kaldıracaksınız.

1. adım: Düzen dosyasına veri bağlama ekleyin

  1. list_item_sleep_night.xml düzen dosyasını Metin sekmesinde açın.
  2. İmleci ConstraintLayout etiketinin üzerine getirin ve Alt+Enter tuşuna (Mac'te Option+Enter ) basın. Amaç menüsü ("hızlı düzeltme" menüsü) açılır.
  3. Veri bağlama düzenine dönüştür'ü seçin. Bu işlem, düzeni <layout> içine sarar ve içine bir <data> etiketi ekler.
  4. Gerekirse en üste geri kaydırın ve <data> etiketi içinde sleep adlı bir değişken tanımlayın.
  5. type, SleepNight'nin tam nitelikli adı olmalıdır, com.example.android.trackmysleepquality.database.SleepNight. Tamamlanmış <data> etiketiniz aşağıdaki gibi görünmelidir.
   <data>
        <variable
            name="sleep"
            type="com.example.android.trackmysleepquality.database.SleepNight"/>
    </data>
  1. Binding nesnesinin oluşturulmasını zorlamak için Build > Clean Project'i (Derle > Projeyi Temizle) ve ardından Build > Rebuild Project'i (Derle > Projeyi Yeniden Derle) seçin. (Hâlâ sorun yaşıyorsanız Dosya > Önbellekleri Geçersiz Kıl / Yeniden Başlat'ı seçin.) İlgili kodla birlikte ListItemSleepNightBinding bağlama nesnesi, projenin oluşturulan dosyalarına eklenir.

2. adım: Veri bağlama kullanarak öğe düzenini genişletin

  1. SleepNightAdapter.kt adlı kişiyi aç.
  2. ViewHolder sınıfında from() yöntemini bulun.
  3. view değişkeninin bildirimini silin.

Silinecek kod:

val view = layoutInflater
       .inflate(R.layout.list_item_sleep_night, parent, false)
  1. view değişkeninin bulunduğu yerde, aşağıdaki örnekte gösterildiği gibi ListItemSleepNightBinding bağlama nesnesini genişleten binding adlı yeni bir değişken tanımlayın. Bağlama nesnesinin gerekli içe aktarma işlemini yapın.
val binding =
ListItemSleepNightBinding.inflate(layoutInflater, parent, false)
  1. İşlevin sonunda view değerini döndürmek yerine binding değerini döndürün.
return ViewHolder(binding)
  1. Hatayı düzeltmek için imlecinizi binding kelimesinin üzerine getirin. Amacınıza uygun menüyü açmak için Alt+Enter (Mac'te Option+Enter) tuşuna basın.
  1. Change parameter 'itemView' type of primary constructor of class 'ViewHolder' to 'ListItemSleepNightBinding' (Sınıfın birincil oluşturucusunun "itemView" parametre türünü "ListItemSleepNightBinding" olarak değiştir) seçeneğini belirleyin. Bu işlem, ViewHolder sınıfının parametre türünü günceller.

  1. İmzadaki değişikliği görmek için ViewHolder sınıf tanımına doğru yukarı kaydırın. itemView yönteminde itemView değerini binding olarak değiştirdiğiniz için itemView ile ilgili bir hata görüyorsunuz.

    ViewHolder sınıf tanımında, itemView değerinin oluşumlarından birini sağ tıklayın ve Yeniden düzenle > Yeniden adlandır'ı seçin.from() Adı binding olarak değiştirin.
  2. Oluşturucu parametresinin binding başına val ekleyerek bunu bir özellik haline getirin.
  3. RecyclerView.ViewHolder üst sınıfına yapılan çağrıda parametreyi binding değerinden binding.root değerine değiştirin. View değerini iletmeniz gerekir ve binding.root, öğe düzeninizdeki kök ConstraintLayout'dir.
  4. Tamamlanmış sınıf beyanınız aşağıdaki koda benzemelidir.
class ViewHolder private constructor(val binding: ListItemSleepNightBinding) : RecyclerView.ViewHolder(binding.root){

Ayrıca findViewById() çağrılarıyla ilgili bir hata görürsünüz ve bunu bir sonraki adımda düzeltirsiniz.

3. adım: findViewById() işlevini değiştirin

Artık sleepLength, quality ve qualityImage özelliklerini findViewById() yerine binding nesnesini kullanacak şekilde güncelleyebilirsiniz.

  1. sleepLength, qualityString ve qualityImage başlatmalarını, aşağıda gösterildiği gibi binding nesnesinin görünümlerini kullanacak şekilde değiştirin. Bu işlemden sonra kodunuzda başka hata gösterilmemelidir.
val sleepLength: TextView = binding.sleepLength
val quality: TextView = binding.qualityString
val qualityImage: ImageView = binding.qualityImage

Bağlama nesnesi yerindeyken sleepLength, quality ve qualityImage özelliklerini artık tanımlamanız gerekmez. DataBinding aramaları önbelleğe alacağından bu özelliklerin bildirilmesine gerek yoktur.

  1. sleepLength, quality ve qualityImage mülk adlarını sağ tıklayın. Refactor > Inline'ı seçin veya Control+Command+N tuşuna (Mac'te Option+Command+N) basın.
  2. Uygulamanızı çalıştırın. (Hata varsa projenizi Temizlemeniz ve Yeniden Oluşturmanız gerekebilir.)

Bu görevde, uygulamalarınızdaki verileri ayarlamak için bağlama bağdaştırıcılarıyla birlikte veri bağlamayı kullanacak şekilde uygulamanızı yükseltirsiniz.

Önceki bir codelab'de, LiveData almak ve metin görünümlerinde görüntülenecek biçimlendirilmiş dizeler oluşturmak için Transformations sınıfını kullanmıştınız. Ancak farklı türleri veya karmaşık türleri bağlamanız gerekiyorsa veri bağlamanın bu türleri kullanmasına yardımcı olmak için bağlama bağdaştırıcıları sağlayabilirsiniz. Adaptörleri bağlama, verilerinizi alıp bunları, veri bağlamanın bir görünümü bağlamak için kullanabileceği bir şeye (ör. metin veya resim) uyarlayan adaptörlerdir.

Üç bağlama bağdaştırıcısı uygulayacaksınız: biri kaliteli resim için, diğerleri ise her metin alanı için. Özetle, bağlama bağdaştırıcısı bildirmek için bir öğe ve görünüm alan bir yöntem tanımlar ve bunu @BindingAdapter ile açıklama ekleyerek belirtirsiniz. Dönüşümü yöntemin gövdesinde uygularsınız. Kotlin'de, verileri alan görünüm sınıfında bir bağlama bağdaştırıcısı uzantı işlevi olarak yazabilirsiniz.

1. adım: Bağlama bağdaştırıcıları oluşturun

Bu adımda bir dizi sınıfı içe aktarmanız gerektiğini ve bunların tek tek belirtilmeyeceğini unutmayın.

  1. SleepNightAdapater.kt adlı kişiyi aç.
  2. ViewHolder sınıfında bind() yöntemini bulun ve bu yöntemin ne yaptığını hatırlayın. binding.sleepLength, binding.quality ve binding.qualityImage değerlerini hesaplayan kodu alıp bunun yerine bağdaştırıcı içinde kullanacaksınız. (Şimdilik kodu olduğu gibi bırakın. Daha sonraki bir adımda taşıyacaksınız.)
  3. sleeptracker paketinde BindingUtils.kt adlı bir dosya oluşturup açın.
  4. TextView üzerinde setSleepDurationFormatted adlı bir uzantı işlevi tanımlayın ve SleepNight iletin. Bu işlev, uyku süresini hesaplama ve biçimlendirme konusunda adaptörünüz olacaktır.
fun TextView.setSleepDurationFormatted(item: SleepNight) {}
  1. setSleepDurationFormatted gövdesinde, verileri ViewHolder.bind() bölümünde yaptığınız gibi görünüme bağlayın. convertDurationToFormatted() işlevini çağırın ve ardından TextView öğesinin text özelliğini biçimlendirilmiş metin olarak ayarlayın. (Bu, TextView üzerindeki bir uzantı işlevi olduğundan text mülküne doğrudan erişebilirsiniz.)
text = convertDurationToFormatted(item.startTimeMilli, item.endTimeMilli, context.resources)
  1. Bu bağlama bağdaştırıcısı hakkında veri bağlamaya bilgi vermek için işlevi @BindingAdapter ile açıklama ekleyin.
  2. Bu işlev, sleepDurationFormatted özelliği için bağdaştırıcıdır. Bu nedenle, sleepDurationFormatted değerini @BindingAdapter işlevine bağımsız değişken olarak iletin.
@BindingAdapter("sleepDurationFormatted")
  1. İkinci bağdaştırıcı, uyku kalitesini SleepNight nesnesindeki değere göre ayarlar. TextView üzerinde setSleepQualityString() adlı bir uzantı işlevi oluşturun ve SleepNight değerini iletin.
  2. Gövdede, verileri ViewHolder.bind() bölümünde yaptığınız gibi görünüme bağlayın. convertNumericQualityToString'ı arayıp text'ı ayarlayın.
  3. İşlevi @BindingAdapter("sleepQualityString") ile açıklama ekleyin.
@BindingAdapter("sleepQualityString")
fun TextView.setSleepQualityString(item: SleepNight) {
   text = convertNumericQualityToString(item.sleepQuality, context.resources)
}
  1. Üçüncü bağlama adaptörü, resmi bir resim görünümüne ayarlar. ImageView üzerinde uzantı işlevini oluşturun, setSleepImage'ı çağırın ve ViewHolder.bind()'daki kodu aşağıdaki şekilde kullanın.
@BindingAdapter("sleepImage")
fun ImageView.setSleepImage(item: SleepNight) {
   setImageResource(when (item.sleepQuality) {
       0 -> R.drawable.ic_sleep_0
       1 -> R.drawable.ic_sleep_1
       2 -> R.drawable.ic_sleep_2
       3 -> R.drawable.ic_sleep_3
       4 -> R.drawable.ic_sleep_4
       5 -> R.drawable.ic_sleep_5
       else -> R.drawable.ic_sleep_active
   })
}

2. adım: SleepNightAdapter'ı güncelleyin

  1. SleepNightAdapter.kt adlı kişiyi aç.
  2. Artık veri bağlama ve yeni bağdaştırıcılarınızı kullanarak bu işi sizin için yapabileceğinizden bind() yöntemindeki her şeyi silin.
fun bind(item: SleepNight) {
}
  1. bind() içinde, bağlama nesnesine yeni SleepNight hakkında bilgi vermeniz gerektiğinden item için uyku durumunu atayın.
binding.sleep = item
  1. Bu satırın altına binding.executePendingBindings() ekleyin. Bu çağrı, veri bağlamadan bekleyen bağlamaları hemen yürütmesini isteyen bir optimizasyondur. Görünümlerin boyutlandırılmasını biraz hızlandırabileceğinden, bağlama bağdaştırıcılarını RecyclerView içinde kullanırken her zaman executePendingBindings() işlevini çağırmak iyi bir fikirdir.
 binding.executePendingBindings()

3. adım: XML düzenine bağlamalar ekleyin

  1. list_item_sleep_night.xml adlı kişiyi aç.
  2. ImageView içinde, resmi ayarlayan bağlama bağdaştırıcısıyla aynı ada sahip bir app özelliği ekleyin. Aşağıda gösterildiği gibi sleep değişkenini iletin.

    Bu özellik, bağdaştırıcı aracılığıyla görünüm ile bağlama nesnesi arasında bağlantı oluşturur. sleepImage her referans verildiğinde bağdaştırıcı, SleepNight verilerini uyarlar.
app:sleepImage="@{sleep}"
  1. Aynı işlemi sleep_length ve quality_string metin görünümleri için de yapın. sleepDurationFormatted veya sleepQualityString her referans verildiğinde bağdaştırıcılar, SleepNight'deki verileri uyarlar.
app:sleepDurationFormatted="@{sleep}"
app:sleepQualityString="@{sleep}"
  1. Uygulamanızı çalıştırın. Uygulamanız, eskiden olduğu gibi çalışır. Bağlama bağdaştırıcıları, veriler değiştikçe görünümleri biçimlendirme ve güncelleme işinin tamamını halleder. Böylece ViewHolder basitleşir ve kod, eskisinden çok daha iyi bir yapıya sahip olur.

Son birkaç egzersiz için aynı listeyi görüntülediniz. Bu, Adapter arayüzünün kodunuzu birçok farklı şekilde yapılandırmanıza olanak tanıdığını göstermek için tasarlanmıştır. Kodunuz ne kadar karmaşıksa iyi bir mimari oluşturmak o kadar önemli hale gelir. Üretim uygulamalarında bu kalıplar ve diğerleri RecyclerView ile birlikte kullanılır. Tüm desenler çalışır ve her birinin avantajları vardır. Hangisini seçeceğiniz, ne oluşturduğunuza bağlıdır.

Tebrikler! Bu noktada, Android'de RecyclerView'da uzmanlaşma yolunda önemli bir adım atmış olursunuz.

Android Studio projesi: RecyclerViewDiffUtilDataBinding.

DiffUtil:

  • RecyclerView, iki liste arasındaki farkları hesaplamak için kullanılan DiffUtil adlı bir sınıfa sahiptir.
  • DiffUtil, iki liste arasındaki farkı bulmak için genişlettiğiniz ItemCallBack adlı bir sınıfa sahiptir.
  • ItemCallback sınıfında, areItemsTheSame() ve areContentsTheSame() yöntemlerini geçersiz kılmanız gerekir.

ListAdapter:

  • Ücretsiz olarak liste yönetimi yapmak için RecyclerView.Adapter yerine ListAdapter sınıfını kullanabilirsiniz. Ancak ListAdapter kullanıyorsanız diğer düzenler için kendi bağdaştırıcınızı yazmanız gerekir. Bu nedenle bu codelab'de nasıl yapılacağı gösterilmektedir.
  • Android Studio'da niyet menüsünü açmak için imleci herhangi bir kod öğesinin üzerine getirin ve Alt+Enter (Mac'te Option+Enter) tuşuna basın. Bu menü, özellikle kodu yeniden düzenlemek ve yöntemleri uygulamak için saplar oluşturmak açısından faydalıdır. Menü bağlama duyarlıdır. Bu nedenle, doğru menüyü almak için imleci tam olarak yerleştirmeniz gerekir.

Veri bağlama:

  • Verileri görünümlere bağlamak için öğe düzeninde veri bağlamayı kullanın.

Bağlama adaptörleri:

  • Daha önce verilerden dizeler oluşturmak için Transformations kullandınız. Farklı veya karmaşık türlerdeki verileri bağlamanız gerekiyorsa veri bağlamanın bunları kullanmasına yardımcı olmak için bağlama bağdaştırıcıları sağlayın.
  • Bağlama bağdaştırıcısı bildirmek için bir öğe ve görünüm alan bir yöntem tanımlayın ve yöntemi @BindingAdapter ile ek açıklama olarak belirtin. Kotlin'de bağlama bağdaştırıcısını View üzerinde bir uzantı işlevi olarak yazabilirsiniz. Adaptörün uyarladığı özelliğin adını iletin. Örneğin:
@BindingAdapter("sleepDurationFormatted")
  • XML düzeninde, bağlama bağdaştırıcısıyla aynı ada sahip bir app özelliği ayarlayın. Verilerle birlikte bir değişken iletin. Örneğin:
.app:sleepDurationFormatted="@{sleep}"

Udacity kursları:

Android geliştirici belgeleri:

Diğer kaynaklar:

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

DiffUtil kullanmak için aşağıdakilerden hangileri gereklidir? Uygun olan tüm seçenekleri işaretleyin.

ItemCallBack dersini uzatın.

▢ Geçersiz kıl areItemsTheSame().

▢ Geçersiz kıl areContentsTheSame().

▢ Öğeler arasındaki farkları izlemek için veri bağlamayı kullanın.

Soru 2

Aşağıdakilerden hangisi bağlama bağdaştırıcıları hakkında doğrudur?

▢ Bağlama bağdaştırıcısı, @BindingAdapter ile açıklama eklenmiş bir işlevdir.

▢ Bağlama bağdaştırıcısı kullanarak veri biçimlendirmeyi görünüm tutucudan ayırabilirsiniz.

▢ Bağlama adaptörlerini kullanmak istiyorsanız RecyclerViewAdapter kullanmanız gerekir.

▢ Bağlama bağdaştırıcıları, karmaşık verileri dönüştürmeniz gerektiğinde iyi bir çözümdür.

3. Soru

Ne zaman bağlama adaptörü yerine Transformations kullanmayı düşünmelisiniz? Uygun olan tüm seçenekleri işaretleyin.

▢ Verileriniz basit olmalıdır.

▢ Bir dizeyi biçimlendiriyorsunuz.

▢ Listeniz çok uzun.

ViewHolder yalnızca bir görünüm içeriyor.

Bir sonraki derse başlayın: 7.3: RecyclerView ile GridLayout