Bu codelab, Android Kotlin Temelleri kursuna dahildir. Codelab'ler üzerinden sırayla çalışıyorsanız bu kurstan en iyi şekilde yararlanabilirsiniz. Tüm kurs codelab'leri Android Kotlin Fundamentals codelabs açılış sayfasında listelenmektedir.
Giriş
Bu codelab'de, öğe listelerini görüntülemek için bir RecyclerView
'nin nasıl kullanılacağı gösterilmektedir. Önceki codelab serisindeki uyku izleyici uygulamasını temel alarak, önerilen mimariye sahip bir RecyclerView
kullanarak veri görüntülemenin daha iyi ve çok yönlü bir yolunu öğreneceksiniz.
Bilmeniz gerekenler
Aşağıdaki konular hakkında bilgi sahibi olmalısınız:
- Bir etkinlik, parçalar ve görünümler kullanarak temel kullanıcı arayüzü (UI) oluşturma.
- Parçalar arasında gezinme ve parçaları parçalar arasında aktarmak için
safeArgs
kullanma. - Görünüm modellerini kullanarak model fabrikalarını, dönüşümleri,
LiveData
ve gözlemcilerini görüntüleyin. Room
veritabanı oluşturma, DAO oluşturma ve varlıkları tanımlama.- Veritabanı görevleri ve uzun süreli diğer görevler için eş yordam kullanma.
Neler öğreneceksiniz?
- Öğe listesini görüntülemek için
Adapter
veViewHolder
içerenRecyclerView
nasıl kullanılır?
Yapacaklarınız
- Uyku kalitesi verilerini göstermek üzere
RecyclerView
kullanmak için önceki dersteki TrackMySleepquality uygulamasını değiştirin.
Bu codelab'de, uygulamanın uyku kalitesini izleyen RecyclerView
bölümünü derlersiniz. Uygulama, uyku verilerini zaman içinde depolamak için bir Room
veritabanı kullanır.
Başlangıçtaki uyku izleyici uygulamasında, aşağıdaki resimde gösterildiği gibi parçalarla temsil edilen iki ekran vardır.
Solda gösterilen ilk ekranda izlemeyi başlatmak ve durdurmak için düğmeler bulunur. Bu ekranda kullanıcının tüm uyku verileri de gösterilir. Temizle düğmesi, uygulamanın kullanıcı için topladığı tüm verileri kalıcı olarak siler. Sağ tarafta gösterilen ikinci ekran uyku kalitesi puanı seçmek içindir.
Bu uygulama, kullanıcı arayüzü denetleyicisi (ViewModel
ve LiveData
) ile basitleştirilmiş bir mimari kullanıyor. Uygulama ayrıca uyku verilerini kalıcı hale getirmek için Room
veritabanı kullanır.
İlk ekranda görüntülenen uyku geceleri listesi işlevsel olsa da pek hoş değildir. Uygulama, metin görünümü için metin dizeleri ve kaliteye yönelik sayılar oluşturmak için karmaşık bir biçimlendirici kullanır. Ayrıca, bu tasarım ölçeklendirilmez. Bu codelab'de tüm bu sorunları düzelttikten sonra nihai uygulama aynı işleve sahip olur ve ana ekran şu şekilde görünür:
Bir liste veya veri tablosu görüntülemek, Android'de en yaygın kullanıcı arayüzü görevlerinden biridir. Listeler basitten çok karmaşıka kadar farklılık gösterir. Metin görüntülemeleri listesinde, alışveriş listesi gibi basit veriler gösterilebilir. Karmaşık bir liste (ör. tatil için takip edilen yerler listesi) kullanıcıya kaydırmalı bir tablo içinde başlık içeren birçok ayrıntı gösterebilir.
Tüm bu kullanım alanlarını desteklemek için Android, RecyclerView
widget'ını sağlar.
RecyclerView
ürününün en büyük avantajı, büyük listeler için çok verimli olmasıdır:
- Varsayılan olarak,
RecyclerView
yalnızca şu anda ekranda görünen öğeleri işlemek veya çizmek için çalışır. Örneğin, listenizde bin öğe varsa ancak yalnızca 10 öğe gösteriliyorsaRecyclerView
ekranda 10 öğe çizmek için yalnızca yeterli işlemi yapar. Kullanıcı sayfayı kaydırdığındaRecyclerView
ekranda hangi yeni öğelerin olması gerektiğini anlar ve bu öğeleri görüntülemek için yeterli çabayı gösterir. - Bir öğe ekranın dışına kaydırıldığında öğenin görünümleri geri dönüştürülür. Bu, öğenin ekrana kaydıran yeni içerikle doldurulduğu anlamına gelir. Bu
RecyclerView
davranışı, çok fazla işlem süresi kazandırır ve listelerin değişken şekilde kaydırılmasına yardımcı olur. - Bir öğe değiştiğinde, listenin tamamını yeniden çizmek yerine
RecyclerView
söz konusu öğeyi güncelleyebilir. Bu, karmaşık öğelerin listelerini görüntülerken büyük bir verimlilik artışı sağlar.
Aşağıda gösterilen sırayla, bir görünümün (ABC
) verilerle doldurulduğunu görebilirsiniz. Bu görünüm ekranın dışına kaydırıldıktan sonra RecyclerView
, yeni veriler için (XYZ
) görünümü yeniden kullanır.
Adaptör deseni
Farklı elektrik prizleri kullanan ülkeler arasında seyahat ederseniz adaptör kullanarak cihazlarınızı prizlere nasıl bağlayacağınızı biliyorsunuz. Bağdaştırıcı, bir tür fişi bir başkasına dönüştürmenizi sağlar. Bu da bir arayüzü başka bir arayüze dönüştürür.
Yazılım mühendisliğindeki uyarlayıcı kalıbı, bir nesnenin başka bir API ile çalışmasına yardımcı olur. RecyclerView
, uygulama verilerini RecyclerView
Uyku izleyici uygulaması için, Room
veritabanındaki verileri ViewModel
özelliğini değiştirmeden RecyclerView
tarafından nasıl görüntüleneceğini bildiği bir şeye uyarlayan bir adaptör oluşturursunuz.
RecyclerView uygulama
RecyclerView
uygulamasında verilerinizi göstermek için aşağıdaki bölümlere ihtiyacınız vardır:
- Gösterilecek veriler.
- Görüntülemeler için kapsayıcı görevi görmek üzere düzen dosyanızda tanımlanan bir
RecyclerView
örneği. - Tek bir veri öğesinin düzeni.
Tüm liste öğeleri aynı görünüyorsa tüm öğeler için aynı düzeni kullanabilirsiniz ancak bu zorunlu değildir. Her defasında bir öğe görünümünün verilerle doldurulabilmesi için öğe düzeninin parçanın düzeninden ayrı olarak oluşturulması gerekir. - Düzen yöneticisi.
Düzen yöneticisi, bir görünümdeki kullanıcı arayüzü bileşenlerinin düzenini (düzenini) yönetir. - Bir görünüm sahibi.
Görünüm sahibi,ViewHolder
sınıfını genişletir. Öğenin düzeninden bir öğeyi görüntülemek için görüntüleme bilgilerini içerir. Görünüm sahipleri,RecyclerView
adlı kullanıcının görünümü etkili şekilde taşımak için kullandığı bilgileri de ekler. - Adaptör.
Bağdaştırıcı, verileriniziRecyclerView
hizmetine bağlar. VerileriViewHolder
içinde görüntülenebilecek şekilde uyarlar.RecyclerView
, verilerin ekranda nasıl görüntüleneceğini öğrenmek için adaptörü kullanır.
Bu görevde düzen dosyanıza bir RecyclerView
ekler ve RecyclerView
verilerini uyku verilerine göstermek için bir Adapter
ayarlarsınız.
1. Adım: LayoutManager ile RecyclerView'u ekleme
Bu adımda, fragment_sleep_tracker.xml
dosyasındaki ScrollView
öğesini RecyclerView
ile değiştirirsiniz.
- GitHub'dan RecyclerViewFundamentals-Starter uygulamasını indirin.
- Uygulamayı oluşturup çalıştırın. Verilerin nasıl basit metin olarak gösterildiğine dikkat edin.
- Android Studio'daki Tasarım sekmesinde
fragment_sleep_tracker.xml
düzen dosyasını açın. - Bileşen Ağacı bölmesinde
ScrollView
öğesini silin. Bu işlem,ScrollView
içindekiTextView
öğelerini de siler. - Palet bölmesinde, sol taraftaki bileşen türleri listesinde gezinerek Kapsayıcılar'ı bulun ve seçin.
- Palet bölmesinden bir
RecyclerView
bileşenini Bileşen Ağacı bölmesine sürükleyin.RecyclerView
öğesiniConstraintLayout
öğesinin içine yerleştirin.
- Bağımlılık eklemek isteyip istemediğinizi soran bir iletişim kutusu açılırsa Android Studio'nun
recyclerview
bağımlısını Gradle dosyanıza eklemesine izin vermek için Tamam'ı tıklayın. Bu işlem birkaç saniye sürebilir ve uygulamanız senkronize edilir.
- Modül
build.gradle
dosyasını açın, sonuna gidin ve aşağıdaki koda benzer şekilde görünen yeni bağımlılığı not edin:
implementation 'androidx.recyclerview:recyclerview:1.0.0'
fragment_sleep_tracker.xml
uygulamasına geri dön.- Text (Metin) sekmesinde, aşağıda gösterilen
RecyclerView
kodunu bulun:
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent" />
sleep_list
içinRecyclerView
id
verin.
android:id="@+id/sleep_list"
ConstraintLayout
içindeRecyclerView
, ekranın kalan kısmını kaplayacak şekilde konumlandırın. Bunu yapmak içinRecyclerView
öğesinin üst kısmını Başlat düğmesine, en alttaki Temizle düğmesine ve her bir tarafı üst öğeye yerleştirin. Aşağıdaki kodu kullanarak Düzen Düzenleyici'de veya XML'de düzen genişliğini ve yüksekliğini 0 dp olarak ayarlayın:
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="@+id/clear_button"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/stop_button"
RecyclerView
XML'ye bir düzen yöneticisi ekleyin. HerRecyclerView
, listedeki öğelerin nasıl konumlanacağını belirten bir düzen yöneticisine ihtiyaç duyar. Android, varsayılan olarak öğeleri tam genişlikli satırlardan oluşan dikey bir listeye yerleştiren birLinearLayoutManager
sağlar.
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
- Tasarım sekmesine geçin. Eklenen kısıtlamaların mevcut alanı dolduracak şekilde
RecyclerView
genişlemesine neden olduğunu fark edin.
2. Adım: Liste öğesi düzenini ve metin görünümü sahibini oluşturun
RecyclerView
yalnızca bir kapsayıcıdır. Bu adımda, RecyclerView
içinde gösterilecek öğelerin düzenini ve altyapısını oluşturursunuz.
Çalışan bir RecyclerView
ürününe mümkün olduğunca hızlı bir şekilde ulaşmak için ilk olarak yalnızca uyku kalitesini sayı olarak gösteren basit bir liste öğesi kullanırsınız. Bunun için bir görünüm sahibine (TextItemViewHolder
) ihtiyacınız var. Ayrıca veriler için bir görünüme (TextView
) ihtiyacınız vardır. (Daha sonraki bir adımda, görüntüleme sahipleri ve tüm uyku verilerini ayarlama hakkında daha fazla bilgi edineceksiniz.)
text_item_view.xml
adlı bir düzen dosyası oluşturun. Şablon kodunu değiştireceğiniz için kök öğe olarak ne kullandığınız önemli değildir.text_item_view.xml
uygulamasında verilen tüm kodu silin.- Başında ve sonunda
16dp
dolgu bulunan birTextView
ve metin boyutu24sp
ekleyin. Genişlikle üst öğe eşleşmelidir ve yükseklik, içeriği sarmalar. Bu görünümRecyclerView
içinde görüntülendiğinden, birViewGroup
içine yerleştirmeniz gerekmez.
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:textSize="24sp"
android:paddingStart="16dp"
android:paddingEnd="16dp"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
Util.kt
'yi açın. Sona ilerleyin ve aşağıda gösterilen tanımı ekleyin. Bu,TextItemViewHolder
sınıfını oluşturur. Kodu, dosyanın en altına, son kapanış ayracından sonra yerleştirin. Bu görünüm sahibi geçici olduğu ve kodu daha sonra değiştirdiğiniz için kodUtil.kt
olarak girilir.
class TextItemViewHolder(val textView: TextView): RecyclerView.ViewHolder(textView)
- İstenirse
android.widget.TextView
veandroidx.recyclerview.widget.RecyclerView
içe aktarın.
3. Adım: SleepNightAdapter oluşturun
Bir RecyclerView
uygulamanın temel görevi, adaptörü oluşturmaktır. Öğe görünümü için basit bir görünüm sahibiniz ve her öğe için bir düzeniniz vardır. Artık bir adaptör oluşturabilirsiniz. Adaptör, bir görünüm sahibi oluşturur ve RecyclerView
öğesinin görüntülenmesi için bu veri ve dolguyu doldurur.
sleeptracker
paketindeSleepNightAdapter
adlı yeni bir Kotlin sınıfı oluşturun.SleepNightAdapter
sınıfınınRecyclerView.Adapter
olmasını sağlayın.SleepNight
nesnesi,RecyclerView
tarafından kullanılabilecek şekilde uyarlandığı için sınıfaSleepNightAdapter
adı verilir. Bağdaştırıcının hangi görüntüleme sahibinin kullanılacağını bilmesi gerektiğindenTextItemViewHolder
içinde iletmeniz gerekir. İstendiğinde gerekli bileşenleri içe aktardığınızda uygulanması gereken zorunlu yöntemler olduğu için bir hata mesajı görürsünüz.
class SleepNightAdapter: RecyclerView.Adapter<TextItemViewHolder>() {}
- Verileri muhafazaya almak için
SleepNightAdapter
üst düzeyinde birlistOf
SleepNight
değişkeni oluşturun.
var data = listOf<SleepNight>()
SleepNightAdapter
içinde,data
içindeki uyku geceleri listesinin boyutunu döndürmek içingetItemCount()
değerini geçersiz kılın.RecyclerView
, adaptörün kaç öğeyi görüntüleyebileceğini bilmelidir ve bunugetItemCount()
çağırarak yapar.
override fun getItemCount() = data.size
SleepNightAdapter
uygulamasındaonBindViewHolder()
işlevini aşağıda gösterildiği gibi geçersiz kılın.onBindViewHolder()
işlevi, belirtilen konumdaki bir liste öğesinin verilerini görüntülemek içinRecyclerView
tarafından çağrılır. Dolayısıyla,onBindViewHolder()
yöntemi iki bağımsız değişken alır: bir görünüm sahibi ve verilerin bağlanacağı konum. Bu uygulama için sahip,TextItemViewHolder
ve konum listedeki konumdur.
override fun onBindViewHolder(holder: TextItemViewHolder, position: Int) {
}
onBindViewHolder()
içinde, verideki belirli bir konumdaki bir öğe için değişken oluşturun.
val item = data[position]
- Oluşturduğunuz
ViewHolder
,textView
adlı bir özelliğe sahip.onBindViewHolder()
içindetextView
text
öğesini uyku kalitesi numarasına ayarlayın. Bu kodda yalnızca numaraların listesi gösterilir. Ancak bu basit örnek, bağdaştırıcının verileri görünüm sahibine ve ekrana nasıl getirdiğini görmenizi sağlar.
holder.textView.text = item.sleepQuality.toString()
SleepNightAdapter
içindeonCreateViewHolder()
öğesini geçersiz kılın ve uygulayın. Bu işlem,RecyclerView
bir öğeyi temsil etmek için görünüm sahibine ihtiyaç duyduğunda çağrılır.
Bu işlev iki parametre alır veViewHolder
döndürür. Görünüm sahibini içeren görüntüleme grubu olanparent
parametresi her zamanRecyclerView
değeridir.viewType
parametresi, aynıRecyclerView
içinde birden çok görünüm olduğunda kullanılır. Örneğin, aynıRecyclerView
içinde metin görüntülemeleri, resim ve video listelerini yerleştirirsenizonCreateViewHolder()
işlevinin ne tür bir görünüm kullanacağını bilmesi gerekir.
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TextItemViewHolder {
}
onCreateViewHolder()
içindeLayoutInflater
örneğini oluşturun.
Düzenleyici, XML düzenlerinden nasıl görünüm oluşturacağınızı bilir.context
, görünümün doğru şekilde nasıl yükseltileceğiyle ilgili bilgiler içerir. Geri dönüşüm görünümü için bir adaptördeparent
görünüm grubu (RecyclerView
) bağlamında her zaman geçiş yaparsınız.
val layoutInflater = LayoutInflater.from(parent.context)
onCreateViewHolder()
içinde,layoutinflater
adlı kişiden şişirmeyi isteyerekview
oluşturun.
Görünüm için XML düzenini ve görünüm içinparent
görünüm grubunu iletin. Üçüncü Boole bağımsız değişkeniattachToRoot
. Bu bağımsız değişkeninfalse
olması gerekir. ÇünküRecyclerView
, zamanı geldiğinde bu öğeyi sizin için görüntüleme hiyerarşisine ekler.
val view = layoutInflater
.inflate(R.layout.text_item_view, parent, false) as TextView
onCreateViewHolder()
içinde,view
ile yapılmış birTextItemViewHolder
döndürün.
return TextItemViewHolder(view)
RecyclerView
veriler hakkında bilgi sahibi olmadığı için adaptöründata
değiştiğindeRecyclerView
öğesini bilgilendirmesi gerekir. Yalnızca bağdaştırıcının ona verdiği görüntüleme sahiplerini bilir.
Gösterdiği veriler değiştiğindeRecyclerView
adlı kullanıcıya bildirmek içinSleepNightAdapter
sınıfının en üstündekidata
değişkenine özel bir değiştirici ekleyin. Ayarlayıcıda,data
için yeni bir değer belirleyin, ardından listeyi yeni verilerle yeniden tetiklemeyi tetiklemek içinnotifyDataSetChanged()
numarasını arayın.
var data = listOf<SleepNight>()
set(value) {
field = value
notifyDataSetChanged()
}
4. Adım: RecyclerView'dan Bağdaştırıcı hakkında bilgi verin
RecyclerView
, görünüm sahiplerini almak için kullanılacak adaptör hakkında bilgi sahibi olmalıdır.
SleepTrackerFragment.kt
'yi açın.onCreateview()
bölgesinde bir adaptör oluşturun. Bu kodu,ViewModel
modelinin oluşturulmasından sonra vereturn
ifadesinden önce yerleştirin.
val adapter = SleepNightAdapter()
adapter
,RecyclerView
ile ilişkilendirin.
binding.sleepList.adapter = adapter
binding
nesnesini güncellemek için projenizi temizleyip yeniden oluşturun.binding.sleepList
veyabinding.FragmentSleepTrackerBinding
ile ilgili hatalar görmeye devam ederseniz önbellekleri geçersiz kılın ve yeniden başlatın. (Dosya > Önbellekleri Geçersiz Kıl / Yeniden Başlat'ı seçin.)
Uygulamayı şimdi çalıştırırsanız herhangi bir hata oluşmaz, ancak Başlat'a ve ardından Durdur'a dokunduğunuzda görüntülenen hiçbir veri görmezsiniz.
5. Adım: Verileri bağdaştırıcıya aktarın
Şu ana kadar bir adaptör ve bağdaştırıcıdan verileri RecyclerView
almanın bir yolu var. Şimdi ViewModel
kaynağından adaptöre veri almanız gerekiyor.
SleepTrackerViewModel
'yi açın.- Tüm uyku gecelerini depolayacak
nights
değişkenini bulun.nights
değişkeni, veritabanındagetAllNights()
çağrısı yapılarak ayarlanır. - Bu değişkene erişmesi gereken bir gözlemci oluşturacağınız için
private
öğesininights
öğesinden kaldırın. Beyanınız aşağıdaki gibi görünmelidir:
val nights = database.getAllNights()
database
paketindeSleepDatabaseDao
öğesini açın.getAllNights()
işlevini bulun. Bu işlevin,SleepNight
değerleri listesiniLiveData
olarak döndürdüğüne dikkat edin. Yaninights
değişkeni,Room
tarafından güncellenenLiveData
değerini içerir ve ne zaman değiştiğini öğrenmek içinnights
değerini gözlemleyebilirsiniz.SleepTrackerFragment
'yi açın.onCreateView()
içinde,adapter
değerinin oluşturulmasının altındanights
değişkeninde bir gözlemci oluşturun.
Ömür boyu sahip olarak parçanınviewLifecycleOwner
özelliğini sağlayarak bu gözlemcinin yalnızcaRecyclerView
ekranda olduğunda etkin olmasını sağlayabilirsiniz.
sleepTrackerViewModel.nights.observe(viewLifecycleOwner, Observer {
})
- Gözlemcinin içinde, null olmayan bir değer (
nights
için) her aldığınızda değeri adaptöredata
atayın. Bu, gözlemleyen için tamamlanmış koddur ve verileri ayarlar:
sleepTrackerViewModel.nights.observe(viewLifecycleOwner, Observer {
it?.let {
adapter.data = it
}
})
- Kodunuzu oluşturun ve çalıştırın.
Adaptörünüz çalışıyorsa uyku kalitesi numaralarını liste olarak görürsünüz. Soldaki ekran görüntüsünde Başlat'a dokunduğunuzda -1 değeri gösterilir. Sağ taraftaki ekran görüntüsünde, Durdur'a dokunup kalite puanı seçtikten sonra, güncellenen uyku kalitesi numarası gösterilir.
6. Adım: Görüntüleme sahiplerinin nasıl geri dönüştürüldüğünü keşfedin
RecyclerView
, görünüm sahiplerini geri dönüştürür. Bu durumda, kartları yeniden kullanır. Bir görünüm ekranın dışına kaydırıldığında RecyclerView
, ekrana kaydırmak üzere olan görünümün görünümünü yeniden kullanır.
Bu görüntüleme sahipleri geri dönüştürüldüğünden, onBindViewHolder()
'in önceki öğelerin bir görünüm sahibi üzerinde ayarlamış olabileceği özelleştirmeleri ayarladığından veya sıfırladığından emin olun.
Örneğin, kalite puanları 1'den küçük veya 1'e eşit olan ve kötü uykuyu temsil eden görüntüleme sahiplerinde metin rengini kırmızı olarak ayarlayabilirsiniz.
SleepNightAdapter
sınıfında,onBindViewHolder()
kodunun sonuna aşağıdaki kodu ekleyin.
if (item.sleepQuality <= 1) {
holder.textView.setTextColor(Color.RED) // red
}
- Uygulamayı çalıştırın.
- Düşük uyku kalitesine sahip bazı veriler eklediğinizde numara kırmızı olur.
- Ekranda kırmızı bir yüksek değer görene kadar uyku kalitesi için yüksek puanlar ekleyin.
RecyclerView
, görünüm sahiplerini yeniden kullandığında sonuçta yüksek kaliteli bir puan için kırmızı görüntüleme sahiplerinden birini yeniden kullanır. Yüksek derecelendirme yanlışlıkla kırmızı renkte gösterilir.
- Bunu düzeltmek için renk kalitesinden küçük veya eşit değilse rengi siyah olarak ayarlamak için bir
else
ifadesi ekleyin.
Her iki koşul da açık olduğunda görünüm sahibi her öğe için doğru metin rengini kullanır.
if (item.sleepQuality <= 1) {
holder.textView.setTextColor(Color.RED) // red
} else {
// reset
holder.textView.setTextColor(Color.BLACK) // black
}
- Uygulamayı çalıştırın; sayıların her zaman doğru renge sahip olması gerekir.
Tebrikler! Artık tamamen işlevsel bir RecyclerView
sürümüne sahipsiniz.
Bu görevde basit görünüm sahibini uyku gecesi için daha fazla veri gösterebilecek bir kişi ile değiştirirsiniz.
Util.kt
öğesine eklediğiniz basit ViewHolder
, bir TextItemViewHolder
içinde TextView
öğesini sarmalar.
class TextItemViewHolder(val textView: TextView): RecyclerView.ViewHolder(textView)
RecyclerView
, neden doğrudan TextView
kullanmıyor? Bu tek kod satırı birçok işlev sağlıyor. ViewHolder
, bir öğenin görünümünü ve RecyclerView
içindeki konumuyla ilgili meta verileri açıklar. RecyclerView
, liste kaydırılırken görünümü doğru şekilde konumlandırmak ve Adapter
öğesinde öğeler eklendiğinde veya kaldırıldığında animasyon görünümleri gibi ilginç şeyler yapmak için bu işlevi kullanır.
RecyclerView
ürününün, ViewHolder
içinde depolanan görünümlere erişmesi gerekiyorsa bunu görünüm sahibinin itemView
özelliğini kullanarak yapabilirsiniz. RecyclerView
, bir öğeyi ekranda görüntülenecek bir bağlama yaparken, kenarlık gibi bir görünümün etrafına çizim yaparken ve erişilebilirliği uygularken itemView
kullanır.
1. Adım: Öğe düzenini oluşturun
Bu adımda, bir öğe için düzen dosyasını oluşturursunuz. Düzen, uyku kalitesi için ImageView
, uyku uzunluğu için TextView
ve metin olarak kalite için TextView
içeren bir ConstraintLayout
içerir. Daha önce düzenleri oluşturduğunuz için sağlanan XML kodunu kopyalayıp yapıştırın.
- Yeni bir düzen kaynağı dosyası oluşturun ve dosyaya
list_item_sleep_night
adını verin. - Dosyadaki kodun tamamını aşağıdaki kodla değiştirin. Ardından, oluşturduğunuz düzen hakkında bilgi edinin.
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/quality_image"
android:layout_width="@dimen/icon_size"
android:layout_height="60dp"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:srcCompat="@drawable/ic_sleep_5" />
<TextView
android:id="@+id/sleep_length"
android:layout_width="0dp"
android:layout_height="20dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/quality_image"
app:layout_constraintTop_toTopOf="@+id/quality_image"
tools:text="Wednesday" />
<TextView
android:id="@+id/quality_string"
android:layout_width="0dp"
android:layout_height="20dp"
android:layout_marginTop="8dp"
app:layout_constraintEnd_toEndOf="@+id/sleep_length"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="@+id/sleep_length"
app:layout_constraintTop_toBottomOf="@+id/sleep_length"
tools:text="Excellent!!!" />
</androidx.constraintlayout.widget.ConstraintLayout>
- Android Studio'da Tasarım sekmesine geçin. Tasarım görünümünde düzeniniz aşağıdaki ekran görüntüsünde yer alır. Şema görünümündeyken sağ taraftaki ekran görüntüsüne benzer.
2. Adım: ViewHolder oluşturun
SleepNightAdapter.kt
'yi açın.SleepNightAdapter
içindeViewHolder
adlı bir sınıf oluşturun veRecyclerView.ViewHolder
süresini uzatın.
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView){}
ViewHolder
içindeki görüntülemeler için referanslar alın. BuViewHolder
öğesinin güncelleyeceği görünümler için bir referansa ihtiyacınız var. BuViewHolder
özelliğini her bağladığınızda, resme ve her iki metin görünümüne erişmeniz gerekir. (Bu kodu daha sonra veri bağlamayı kullanmak için dönüştürürsiniz.)
val sleepLength: TextView = itemView.findViewById(R.id.sleep_length)
val quality: TextView = itemView.findViewById(R.id.quality_string)
val qualityImage: ImageView = itemView.findViewById(R.id.quality_image)
3. Adım: SleepNightAdapter'da ViewHolder'ı kullanın
SleepNightAdapter
tanımında,TextItemViewHolder
yerine yeni oluşturduğunuzSleepNightAdapter.ViewHolder
özelliğini kullanın.
class SleepNightAdapter: RecyclerView.Adapter<SleepNightAdapter.ViewHolder>() {
onCreateViewHolder()
uygulamasını güncelleyin:
ViewHolder
özelliğini döndürmek içinonCreateViewHolder()
imzasını değiştirin.list_item_sleep_night
olan düzen düzenini kullanmak için düzen şişiriciyi değiştirin.TextView
adlı oyuncuyu kaldır.TextItemViewHolder
değeri yerine birViewHolder
döndürün.
Burada tamamlanmış sononCreateViewHolder()
işlevi verilmiştir:
override fun onCreateViewHolder(
parent: ViewGroup, viewType: Int): ViewHolder {
val layoutInflater =
LayoutInflater.from(parent.context)
val view = layoutInflater
.inflate(R.layout.list_item_sleep_night,
parent, false)
return ViewHolder(view)
}
onBindViewHolder()
uygulamasını güncelleyin:
onBindViewHolder()
öğesinin imzasını,holder
parametresiTextItemViewHolder
yerineViewHolder
olacak şekilde değiştirin.onBindViewHolder()
içinde,item
tanımı hariç tüm kodu silin.- Bu görünüm için
resources
öğesine referans veren birval
res
tanımlayın.
val res = holder.itemView.context.resources
sleepLength
metin görünümünün metnini süre olarak ayarlayın. Aşağıdaki kodu kopyalayın. Bu ad, başlangıç koduyla sağlanan bir biçimlendirme işlevini çağırır.
holder.sleepLength.text = convertDurationToFormatted(item.startTimeMilli, item.endTimeMilli, res)
- Bu,
convertDurationToFormatted()
öğesinin tanımlanması gerektiğinden bir hata verir.Util.kt
uygulamasını açın ve kodla ilişkili kodu ve ilişkili içe aktarma işlemlerini iptal edin. (Kod > Satır Yorumları ile Yorum'u seçin.) - Kaliteyi ayarlamak için
onBindViewHolder()
değeriniconvertNumericQualityToString()
kullanın.
holder.quality.text= convertNumericQualityToString(item.sleepQuality, res)
- Bu işlevleri manuel olarak içe aktarmanız gerekebilir.
import com.example.android.trackmysleepquality.convertDurationToFormatted
import com.example.android.trackmysleepquality.convertNumericQualityToString
- Kalite için doğru simgeyi ayarlayın. Yeni
ic_sleep_active
simgesi, başlangıç kodu içinde sunulur.
holder.qualityImage.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
})
ViewHolder
için tüm verileri ayarlayarak, güncellenen güncellenmişonBindViewHolder()
işlevini burada bulabilirsiniz:
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val item = data[position]
val res = holder.itemView.context.resources
holder.sleepLength.text = convertDurationToFormatted(item.startTimeMilli, item.endTimeMilli, res)
holder.quality.text= convertNumericQualityToString(item.sleepQuality, res)
holder.qualityImage.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
})
}
- Uygulamanızı çalıştırın. Ekranınız, uyku kalitesi simgesini ve uyku kalitesi ile uyku kalitesini gösteren aşağıdaki ekran görüntüsüne benzemelidir.
RecyclerView
cihazınız artık tamamlandı. Bir Adapter
ve ViewHolder
yapmayı öğrendiniz ve RecyclerView
Adapter
içeren bir liste görüntülemek için bunları bir araya getirdiniz.
Şimdiye kadar kodunuz, adaptör oluşturma ve görüntüleme sahibi işlemini gösterir. Ancak bu kodu daha iyi hale getirebilirsiniz. Gösterilecek kod ve görüntüleme sahiplerini yönetme kodu karışıktır ve onBindViewHolder()
, ViewHolder
öğesinin nasıl güncelleneceğine dair ayrıntıları bilir.
Üretim uygulamasında birden fazla görüntüleme sahibi, daha karmaşık bağdaştırıcılar ve değişiklik yapan birden fazla geliştirici olabilir. Kodunuzu, bir görünüm sahibiyle ilgili her şeyin yalnızca görünüm sahibi içinde olacağı şekilde yapılandırmanız gerekir.
1. Adım: onConnectViewHolder() parametresini yeniden düzenleyin
Bu adımda kodu yeniden düzenler ve tüm görüntüleme sahibi işlevlerini ViewHolder
ürününe taşırsınız. Bu yeniden düzenlemenin amacı, uygulamanın kullanıcıya nasıl göründüğünü değiştirmek değil, geliştiricilerin kod üzerinde çalışmasını daha kolay ve daha güvenli hale getirmektir. Neyse ki Android Studio'nun size yardımcı olacak araçları var.
SleepNightAdapter
öğesindeonBindViewHolder()
değişkeniniitem
tanımlaması için ifade hariç her şeyi seçin.- Sağ tıklayıp Yeniden Düzenleme > Ayıklama > İşlevi'ni seçin.
- İşleve
bind
adını verin ve önerilen parametreleri kabul edin. Tamam'ı tıklayın.bind()
işlevionBindViewHolder()
altına yerleştirilir.
private fun bind(holder: ViewHolder, item: SleepNight) {
val res = holder.itemView.context.resources
holder.sleepLength.text = convertDurationToFormatted(item.startTimeMilli, item.endTimeMilli, res)
holder.quality.text = convertNumericQualityToString(item.sleepQuality, res)
holder.qualityImage.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
})
}
- İmleci
bind()
öğesininholder
parametresininholder
kelimesine getirin. Niyet menüsünü açmak içinAlt+Enter
(Mac'teOption+Enter
) tuşuna basın. Bunu, aşağıdaki imzaya sahip bir uzantı işlevine dönüştürmek için Parametreyi alıcıya dönüştür'ü seçin:
private fun ViewHolder.bind(item: SleepNight) {...}
bind()
işlevini kesipViewHolder
içine yapıştırın.bind()
adlı yeri herkese açık hale getirin.- Gerekirse
bind()
adaptörüne aktarın. - Şu anda
ViewHolder
bölümünde olduğundan imzanınViewHolder
kısmını kaldırabilirsiniz.ViewHolder
sınıfındakibind()
işlevinin son kodu aşağıda verilmiştir.
fun bind(item: SleepNight) {
val res = itemView.context.resources
sleepLength.text = convertDurationToFormatted(
item.startTimeMilli, item.endTimeMilli, res)
quality.text = convertNumericQualityToString(
item.sleepQuality, res)
qualityImage.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: onCreateViewHolder için yeniden düzenleme
Adaptördeki onCreateViewHolder()
yöntemi şu anda ViewHolder
için düzen kaynağından görünümü şişiriyor. Ancak, adaptörle ve ViewHolder
ile ilgili her şeyin şişmeyle ilgisi yoktur. ViewHolder
içinde enflasyon oluşmalıdır.
onCreateViewHolder()
içinde işlevin gövdesindeki tüm kodu seçin.- Sağ tıklayıp Yeniden Düzenleme > Ayıklama > İşlevi'ni seçin.
- İşleve
from
adını verin ve önerilen parametreleri kabul edin. Tamam'ı tıklayın. - İmleci
from
adlı işlev adının üzerine getirin. Niyet menüsünü açmak içinAlt+Enter
(Mac'teOption+Enter
) tuşuna basın. - Tamamlayıcı nesneye taşı'yı seçin.
from()
işlevinin,ViewHolder
örneğinde değil,ViewHolder
sınıfında çağrılabilmesi için bir tamamlayıcı nesnesinde olması gerekir. companion
nesnesiniViewHolder
sınıfına taşıyın.from()
adlı yeri herkese açık hale getirin.onCreateViewHolder()
içinde,return
ifadesiniViewHolder
sınıfındafrom()
çağırma sonucunu döndürecek şekilde değiştirin.
TamamladığınızonCreateViewHolder()
vefrom()
yöntemleriniz aşağıdaki koda benzeyecek şekilde olmalı ve kodunuz hatasız olarak oluşturulmalı ve çalıştırılmalıdır.
override fun onCreateViewHolder(parent: ViewGroup, viewType:
Int): ViewHolder {
return ViewHolder.from(parent)
}
companion object {
fun from(parent: ViewGroup): ViewHolder {
val layoutInflater = LayoutInflater.from(parent.context)
val view = layoutInflater
.inflate(R.layout.list_item_sleep_night, parent, false)
return ViewHolder(view)
}
}
- Oluşturanın gizli olması için
ViewHolder
sınıfının imzasını değiştirin.from()
artık yeni birViewHolder
örneği döndüren bir yöntem olduğu için artıkViewHolder
ürününün kurucusunu çağırmanın bir nedeni yok.
class ViewHolder private constructor(itemView: View) : RecyclerView.ViewHolder(itemView){
- Uygulamayı çalıştırın. Uygulamanız, aynı şekilde derlenip çalıştırılmalıdır. Bu işlem, yeniden bakımdan sonra istenen sonuçtur.
Android Studio projesi: RecyclerViewFundamentals
- Bir liste veya veri tablosu görüntülemek, Android'de en yaygın kullanıcı arayüzü görevlerinden biridir.
RecyclerView
, çok büyük listeler görüntülerken bile verimli olacak şekilde tasarlanmıştır. RecyclerView
yalnızca şu anda ekranda görünen öğeleri işlemek veya çizmek için gereken işi yapar.- Bir öğe ekranın dışına kaydırıldığında görünümleri geri dönüştürülmüş hale gelir. Bu, öğenin ekrana kaydıran yeni içerikle doldurulduğu anlamına gelir.
- Yazılım mühendisliğindeki uyarlayıcı kalıbı, bir nesnenin başka bir API ile birlikte çalışmasına yardımcı olur.
RecyclerView
, uygulama verilerini depolayabileceği ve işlemesine gerek kalmadan uygulama verilerini gösterebileceği bir şeye dönüştürmek için bir adaptör kullanır.
RecyclerView
uygulamasında verilerinizi göstermek için aşağıdaki bölümlere ihtiyacınız vardır:
- RecyclerView
RecyclerView
örneği oluşturmak için düzen dosyasında bir<RecyclerView>
öğesi tanımlayın. - LayoutManager
RecyclerView
,RecyclerView
içindeki öğelerin düzenini düzenlemek içinLayoutManager
kullanır. Örneğin, bunları bir ızgaraya veya doğrusal bir listeye yerleştirmek gibi.
Düzen dosyasındaki<RecyclerView>
içinde,app:layoutManager
özelliğini düzen yöneticisine (LinearLayoutManager
veyaGridLayoutManager
gibi) ayarlayın.
Ayrıca,LayoutManager
içinRecyclerView
öğesini programatik olarak da ayarlayabilirsiniz. (Bu teknik daha sonraki bir codelab'de ele alınmıştır.) - Her öğe için düzen
Bir XML düzeni dosyasındaki bir öğe öğesi için düzen oluşturun. - Bağdaştırıcı
Verileri veViewHolder
içinde nasıl görüntüleneceğini hazırlayan bir bağdaştırıcı oluşturun. AdaptörüRecyclerView
ile ilişkilendirin.RecyclerView
çalıştırıldığında adaptörü kullanarak verilerin ekranda nasıl görüntüleneceğini öğrenmek için bu adaptörü kullanır.
Adaptör, aşağıdaki yöntemleri uygulamanızı gerektirir:
- öğe sayısını döndürmek içingetItemCount()
.
-onCreateViewHolder()
bir öğeninViewHolder
değerini döndürmek için.
–onBindViewHolder()
listedeki verileri bir öğenin görüntüleme sayısına uyarlamak için. - ViewHolder
ViewHolder
, öğenin düzenindeki bir öğenin gösterilmesini sağlayan görünüm bilgilerini içerir. - Adaptördeki
onBindViewHolder()
yöntemi, verileri görünümlere uyarlar. Bu yöntemi her zaman geçersiz kılarsınız. GenellikleonBindViewHolder()
, bir öğenin düzenini artırır ve verileri düzendeki görünümlere yerleştirir. RecyclerView
verileri hakkında bilgi sahibi olmadığından,Adapter
bu veriler değiştiğindeRecyclerView
hakkında bilgi vermelidir. Verilerin değiştiğiniAdapter
bildirmek içinnotifyDataSetChanged()
kullanın.
Udacity kursu:
Android geliştirici dokümanları:
Bu bölümde, bir eğitmen tarafından sunulan kurs kapsamında bu codelab üzerinden çalışan öğrenciler için olası ev ödevi ödevleri listelenmektedir. Öğretmenin şunları yapması gerekir:
- Gerekirse ev ödevini atayın.
- Öğrencilere ev ödevlerinin nasıl gönderileceğini bildirin.
- Ev ödevlerine not verin.
Öğretmenler bu önerileri istedikleri kadar kullanabilir veya uygun görebilir ve uygun olan diğer ev ödevlerini atayabilirler.
Bu codelab'de kendiniz çalışıyorsanız, bilginizi test etmek için bu ödevlerden yararlanabilirsiniz.
Bu soruları yanıtlayın
1. Soru
RecyclerView
öğeleri nasıl gösterir? Geçerli olan tüm seçenekleri işaretleyin.
▢ Öğeleri bir listede veya ızgarada görüntüler.
▢ Dikey veya yatay olarak kaydırılır.
▢ Tabletler gibi daha büyük cihazlarda çapraz olarak kaydırılır.
▢ Bir kullanım alanı için liste veya tablo yeterli olmadığında özel düzenlere izin verir.
2. Soru
RecyclerView
kullanmanın avantajları nelerdir? Geçerli olan tüm seçenekleri işaretleyin.
▢ Büyük listeleri verimli bir şekilde gösterir.
▢ Verileri otomatik olarak günceller.
▢ Bir öğe güncellendiğinde, silindiğinde veya listeye eklendiğinde yenileme ihtiyacını en aza indirir.
▢ Ekranı kaydırarak açılan bir sonraki öğeyi görüntülemek için ekranın dışına kaydırılan görünümü yeniden kullanır.
3. Soru
Adaptörleri kullanmanın nedenlerinden bazıları nelerdir? Geçerli olan tüm seçenekleri işaretleyin.
arasındaki endişelerin birbirinden ayrılması, kodu değiştirmeyi ve test etmeyi kolaylaştırır.
▢ RecyclerView
, gösterilen verilerden bağımsız.
▢ Veri işleme katmanlarının, verilerin nasıl görüntüleneceğiyle ilgili endişe duymaları gerekmez.
▢ Uygulama daha hızlı çalışır.
4. Soru
ViewHolder
ile ilgili olarak aşağıdakilerden hangisi doğrudur? Geçerli olan tüm seçenekleri işaretleyin.
▢ ViewHolder
düzeni XML düzen dosyalarında tanımlanır.
▢ Veri kümesindeki her bir veri birimi için bir ViewHolder
vardır.
RecyclerView
ile birden fazla ViewHolder
ekleyebilirsiniz.
▢ Adapter
, verileri ViewHolder
hizmetine bağlar.
Sonraki derse başlayın: