Halo semuanya! Posting saya adalah keinginan untuk membantu dengan beberapa elemen Android. Jika Anda seorang pengembang yang belum mengembangkan algoritme untuk membuat daftar, Anda mungkin perlu membaca materi ini. Pada dasarnya, saya ingin menawarkan solusi yang siap pakai untuk pengembangan, mengungkapkan dalam jalan cerita beberapa pemikiran tentang bagaimana saya
datang kepada
mereka sampai pada ini.
Dalam artikel ini:- kami membentuk beberapa kelas dasar dan antarmuka untuk bekerja dengan RecyclerView dan RecyclerView.Adapter
- menghubungkan satu perpustakaan dari Android Jetpack (opsional, pertama tanpa itu)
- untuk pengembangan yang lebih cepat - opsi templat di akhir artikel;)
Entri
Baiklah kalau begitu! Semua orang sudah lupa tentang ListView dan aman menulis di RecyclerView (
Rv ). Saat-saat ketika kami menerapkan pola
ViewHolder sendiri telah tenggelam terlupakan.
Rv memberi kami seperangkat kelas siap pakai untuk mengimplementasikan daftar dan pilihan
LayoutManagers yang cukup besar untuk menampilkannya. Bahkan, melihat banyak layar, Anda dapat membayangkan sebagian besar dari mereka sebagai daftar - justru karena kemampuan masing-masing elemen untuk menerapkan
ViewHolder sendiri.
Kami telah diberitahu tentang kisah pengembangan lebih detail
di Google I / O.Tapi, selalu ada beberapa "tetapi!" .. Jawaban standar untuk Stackoverflow menyarankan solusi umum yang mengarah ke salin tempel, terutama di tempat Adaptor diimplementasikan.
Saat ini,
Rv sudah berusia tiga tahun. Ada banyak informasi tentang itu, dan ada banyak perpustakaan dengan solusi yang sudah jadi, tetapi bagaimana jika Anda tidak memerlukan semua fungsionalitas, atau jika Anda naik untuk melihat kode orang lain - dan Anda melihat di sana
Horor Kuno bukan apa yang ingin Anda lihat, atau tidak apa yang ingin Anda lihat. bayangkan? Selama tiga tahun ini, Android akhirnya secara resmi menerima Kotlin = keterbacaan kode telah meningkat, banyak artikel menarik telah diterbitkan di
Rv yang sepenuhnya mengungkapkan kemampuannya.
Tujuannya adalah untuk mengumpulkan dasar dari praktik terbaik
sepeda Anda , kerangka kerja untuk bekerja dengan daftar untuk aplikasi baru. Kerangka kerja ini dapat dilengkapi dengan logika dari aplikasi ke aplikasi, menggunakan apa yang Anda butuhkan dan membuang yang tidak perlu. Saya pikir pendekatan ini jauh lebih baik daripada perpustakaan orang lain - di kelas Anda, Anda memiliki kesempatan untuk memahami bagaimana semuanya bekerja dan untuk mengontrol kasus yang Anda butuhkan tanpa terikat dengan keputusan orang lain.
Mari berfikir logis dan benar dari awal
Apa yang harus dilakukan komponen akan diputuskan oleh
antarmuka, bukan kelas , tetapi pada akhirnya kita akan menutup logika implementasi konkret ke kelas yang akan mengimplementasikan dan mengimplementasikan antarmuka ini. Tetapi, jika ternyata dengan implementasi antarmuka copy-paste terbentuk - kita dapat menyembunyikannya di belakang kelas abstrak, dan setelah itu - kelas yang mewarisi dari abstrak. Saya akan menunjukkan implementasi saya dari antarmuka dasar, tetapi tujuan saya adalah agar pengembang hanya mencoba berpikir ke arah yang sama. Sekali lagi - rencananya adalah ini:
Seperangkat antarmuka -> kelas abstrak yang mengambil salin-tempel (jika perlu) -> dan sudah kelas khusus dengan kode unik . Anda dapat mengimplementasikan antarmuka secara berbeda.
Apa yang bisa dilakukan adaptor dengan daftar? Jawaban atas pertanyaan ini paling mudah didapat ketika Anda melihat beberapa contoh. Anda dapat melihat pada RecyclerView.Adapter, Anda akan menemukan beberapa tips. Jika Anda berpikir sedikit, Anda dapat membayangkan sesuatu seperti metode ini:
IBaseListAdapterinterface IBaseListAdapter<T> { fun add(newItem: T) fun add(newItems: ArrayList<T>?) fun addAtPosition(pos : Int, newItem : T) fun remove(position: Int) fun clearAll() }
* Menelusuri proyek-proyek, saya menemukan beberapa metode lain yang saya akan hilangkan di sini, misalnya getItemByPos (posisi: Int), atau bahkan subList (startIndex: Int, endIndex: Int). Saya ulangi: Anda sendiri harus menonton apa yang Anda butuhkan dari proyek dan memasukkan fungsi dalam antarmuka. Tidak sulit ketika Anda tahu bahwa semuanya terjadi dalam satu kelas. Pertapaan dalam hal ini akan memungkinkan Anda untuk menyingkirkan logika yang tidak perlu, yang menurunkan keterbacaan kode, karena implementasi tertentu membutuhkan lebih banyak baris. Perhatikan
T. generik Secara umum, adaptor bekerja dengan objek apa pun dari daftar (item), jadi tidak ada klarifikasi di sini - kami belum memilih pendekatan kami. Dan dalam artikel ini setidaknya akan ada dua, antarmuka pertama terlihat seperti ini:
interface IBaseListItem { fun getLayoutId(): Int }
Ya, sepertinya logis - kita berbicara tentang item daftar, jadi setiap item harus memiliki semacam tata letak, dan Anda dapat merujuknya menggunakan layoutId. Kemungkinan besar, pengembang pemula mungkin tidak membutuhkan apa-apa, kecuali tentu saja kami mengambil
pendekatan yang lebih
maju . Jika Anda memiliki cukup pengalaman dalam pengembangan, Anda tentu dapat membuat delegasi atau pembungkus, tetapi apakah itu sepadan dengan proyek kecil - dan bahkan pengalaman pengembangan yang lebih sedikit? Semua tautan saya di suatu tempat di YouTube sangat berguna jika Anda tidak punya waktu sekarang - ingat saja dan baca terus, karena pendekatannya lebih sederhana di sini - saya pikir bahwa dengan kerja standar dengan
Rv ,
dilihat dari dokumentasi resmi , apa yang ditawarkan di atas tidak tersirat.
Saatnya untuk menggabungkan
IBaseListAdapter kami dengan antarmuka, dan kelas berikut akan abstrak:
SimpleListAdapter abstract class SimpleListAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>(), IBaseListAdapter<IBaseListItem> { protected val items: ArrayList<IBaseListItem> = ArrayList() override fun getItemCount() = items.size override fun getItemViewType(position: Int) = items[position].layoutId protected fun inflateByViewType(context: Context?, viewType: Int, parent: ViewGroup) = LayoutInflater.from(context).inflate(viewType, parent, false) override fun add(newItem: IBaseListItem) { items.add(newItem) notifyDataSetChanged() } override fun add(newItems: ArrayList<IBaseListItem>?) { for (newItem in newItems ?: return) { items.add(newItem) notifyDataSetChanged() } } override fun addAtPosition(pos: Int, newItem: IBaseListItem) { items.add(pos, newItem) notifyDataSetChanged() } override fun clearAll() { items.clear() notifyDataSetChanged() } override fun remove(position: Int) { items.removeAt(position) notifyDataSetChanged() } }
* Catatan: Perhatikan fungsi
getItemViewType (posisi: Int) yang diganti. Kita memerlukan semacam kunci int, yang dengannya Rv akan memahami ViewHolder mana yang cocok untuk kita.
Tata letak ValId untuk
barang kami sangat berguna untuk ini, seperti Android setiap kali membantu menjadikan id tata letak menjadi unik, dan semua nilai lebih besar dari nol - kami akan menggunakannya nanti untuk "
mengembang "
itemView untuk pemirsa kami dalam metode
inflateByViewType () (baris berikutnya).
Buat daftar
Ambil contoh layar pengaturan. Android menawarkan kepada kita
versinya sendiri, tetapi bagaimana jika desain membutuhkan sesuatu yang lebih canggih? Saya lebih suka mengisi layar ini sebagai daftar. Di sini akan diberikan kasus seperti itu:

Kami melihat dua item daftar yang berbeda, jadi
SimpleListAdapter dan
Rv sempurna di sini!
Ayo mulai! Anda bisa mulai dengan tata letak layout untuk item'ov:
item_info.xml; item_switch.xml <?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="56dp"> <TextView android:id="@+id/tv_info_title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:layout_marginStart="28dp" android:textColor="@color/black" android:textSize="20sp" tools:text="Balance" /> <TextView android:id="@+id/tv_info_value" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical|end" android:layout_marginEnd="48dp" tools:text="1000 $" /> </FrameLayout> <?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="56dp"> <TextView android:id="@+id/tv_switch_title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:layout_marginStart="28dp" android:textColor="@color/black" android:textSize="20sp" tools:text="Send notifications" /> <Switch android:id="@+id/tv_switch_value" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical|end" android:layout_marginEnd="48dp" tools:checked="true" /> </FrameLayout>
Kemudian, kita mendefinisikan kelas-kelas itu sendiri, di dalamnya kita ingin meneruskan nilai-nilai yang berinteraksi dengan daftar: yang pertama adalah header dan beberapa nilai yang datang dari luar (kita akan memiliki sebuah rintisan, tentang permintaan di lain waktu), yang kedua adalah variabel header dan boolean dimana kita harus melakukan suatu tindakan. Untuk membedakan antara elemen Switch, id entitas dari server cocok, jika mereka tidak ada, kita dapat membuatnya sendiri selama inisialisasi.
InfoItem.kt, SwitchItem.kt class InfoItem(val title: String, val value: String): IBaseListItem { override val layoutId = R.layout.item_info } class SwitchItem( val id: Int, val title: String, val actionOnReceive: (itemId: Int, userChoice: Boolean) -> Unit ) : IBaseListItem { override val layoutId = R.layout.item_switch }
Dalam implementasi yang sederhana, setiap elemen juga akan membutuhkan ViewHolder:
InfoViewHolder.kt, SwitchViewHolder.kt class InfoViewHolder.kt(view: View) : RecyclerView.ViewHolder(view) { val tvTitle = view.tv_info_title val tvValue = view.tv_info_value } class SwitchViewHolder.kt(view: View) : RecyclerView.ViewHolder(view) { val tvTitle = view.tv_switch_title val tvValue = view.tv_switch_value }
Nah, bagian yang paling menarik adalah implementasi konkret dari SimpleListAdapter'a:
PengaturanListAdapter.kt class SettingsListAdapter : SimpleListAdapter() { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { val context = parent.context return when (viewType) { R.layout.item_info -> InfoHolder(inflateByViewType(context, viewType, parent)) R.layout.item_switch -> SwitchHolder(inflateByViewType(context, viewType, parent)) else -> throw IllegalStateException("There is no match with current layoutId") } } override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { when (holder) { is InfoHolder -> { val infoItem = items[position] as InfoItem holder.tvTitle.text = infoItem.title holder.tvValue.text = infoItem.value } is SwitchHolder -> { val switchItem = items[position] as SwitchItem holder.tvTitle.text = switchItem.title holder.tvValue.setOnCheckedChangeListener { _, isChecked -> switchItem.actionOnReceive.invoke(switchItem.id, isChecked) } } else -> throw IllegalStateException("There is no match with current holder instance") } } }
* Catatan: Jangan lupa bahwa di bawah kap metode
inflateByViewType (konteks, viewType, induk): viewType = layoutId.Semua komponen sudah siap! Sekarang, kode Aktivitas tetap dan Anda dapat menjalankan program:
activity_settings.xml <?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.v7.widget.RecyclerView android:id="@+id/rView" android:layout_width="match_parent" android:layout_height="match_parent" /> </FrameLayout>
SettingsActivity.kt class SettingsActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_settings) val adapter = SettingsListAdapter() rView.layoutManager = LinearLayoutManager(this) rView.adapter = adapter adapter.add(InfoItem("User Name", "Leo Allford")) adapter.add(InfoItem("Balance", "350 $")) adapter.add(InfoItem("Tariff", "Business")) adapter.add(SwitchItem(1, "Send Notifications") { itemId, userChoice -> onCheck(itemId, userChoice) }) adapter.add(SwitchItem(2, "Send News on Email") { itemId, userChoice -> onCheck(itemId, userChoice) }) } private fun onCheck(itemId: Int, userChoice: Boolean) { when (itemId) { 1 -> Toast.makeText(this, "Notification now set as $userChoice", Toast.LENGTH_SHORT).show() 2 -> Toast.makeText(this, "Send news now set as $userChoice", Toast.LENGTH_SHORT).show() } } }
Akibatnya, saat membuat daftar, semua pekerjaan harus dilakukan sebagai berikut:
1. Perhitungan
jumlah tata letak yang berbeda untuk item
2. Pilih
nama mereka. Saya menggunakan aturan:
Something Item.kt, item_
something .xml,
Something ViewHolder.kt
3. Kami menulis
adaptor ke kelas-kelas ini. Pada prinsipnya, jika Anda tidak berpura-pura mengoptimalkan, maka satu adaptor umum sudah cukup. Tetapi dalam proyek-proyek besar, saya masih akan melakukan beberapa, di layar, karena dalam kasus pertama metode
onBindViewHolder () pasti tumbuh (menderita pembacaan kode) dalam adaptor Anda (dalam kasus kami, itu adalah
SettingsListAdapter ) + program harus berjalan setiap waktu, untuk setiap item, jalankan metode ini + metode
onCreateViewHolder ()4. Jalankan kode dan nikmatilah!
Jetpack
Hingga saat itu, kami menggunakan pendekatan penjilidan data standar dari
Item.kt ke
item_layout.xml kami. Tetapi kita dapat menyatukan metode
onBindViewHolder () , biarkan minimal, dan transfer logika ke Item dan tata letak.
Mari kita buka halaman Android JetPack resmi:

Mari kita perhatikan tab pertama di bagian Arsitektur.
Android Databinding adalah topik yang sangat luas, saya ingin membicarakannya secara lebih rinci di artikel lain, tetapi untuk sekarang kita akan menggunakannya hanya sebagai bagian dari yang sekarang - kita akan membuat
Item.kt -
variabel untuk
item.xml (atau Anda dapat menyebutnya model tampilan untuk tata letak).
Pada saat penulisan,
Databinding dapat dihubungkan seperti ini:
android { compileSdkVersion 27 defaultConfig {...} buildTypes {...} dataBinding { enabled = true } dependencies { kapt "com.android.databinding:compiler:3.1.3"
Mari kita kembali ke kelas dasar. Antarmuka untuk item melengkapi yang sebelumnya:
interface IBaseItemVm: IBaseListItem { val brVariableId: Int }
Juga, kami akan memperluas ViewHolder kami, oleh karena itu, kami dihubungi dengan databyding. Kami akan meneruskan
ViewDataBinding ke sana, setelah itu kami akan dengan aman lupa membuat tata letak dan pengikatan data
class VmViewHolder(val binding: ViewDataBinding) : RecyclerView.ViewHolder(binding.root)
Pendekatan yang sama digunakan di
sini , tetapi di Kotlin terlihat jauh lebih pendek, bukan? =)
VmListAdapter class VmListAdapter : RecyclerView.Adapter<VmViewHolder>(), IBaseListAdapter<IBaseItemVm> { private var mItems = ArrayList<IBaseItemVm>() override fun getItemCount() = mItems.size override fun getItemViewType(position: Int) = mItems[position].layoutId override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): VmViewHolder { val inflater = LayoutInflater.from(parent.context) val viewDataBinding = DataBindingUtil.inflate<ViewDataBinding>(inflater!!, viewType, parent, false) return VmViewHolder(viewDataBinding) } override fun onBindViewHolder(holder: VmViewHolder, position: Int) { holder.binding.setVariable(mItems[position].brVariableId, mItems[position]) holder.binding.executePendingBindings() } override fun add(newItem: IBaseItemVm) { mItems.add(newItem) notifyItemInserted(mItems.lastIndex) } override fun add(newItems: ArrayList<IBaseItemVm>?) { val oldSize = mItems.size mItems.addAll(newItems!!) notifyItemRangeInserted(oldSize, newItems.size) } override fun clearAll() { mItems.clear() notifyDataSetChanged() } override fun getItemId(position: Int): Long { val pos = mItems.size - position return super.getItemId(pos) } override fun addAtPosition(pos: Int, newItem: IBaseItemVm) { mItems.add(pos, newItem) notifyItemInserted(pos) } override fun remove(position: Int) { mItems.removeAt(position) notifyItemRemoved(position) } }
Perhatikan metode
onCreateViewHolder () ,
onBindViewHolder () secara umum . Idenya adalah bahwa mereka tidak lagi tumbuh. Total, Anda mendapatkan satu adaptor untuk layar apa pun, dengan item daftar apa pun.
Barang kami:
InfoItem.kt, SwitchItem.kt class InfoItem(val title: String, val value: String) : IBaseItemVm { override val brVariableId = BR.vmInfo override val layoutId = R.layout.item_info } // class SwitchItem( val id: Int, val title: String, private val actionOnReceive: (itemId: Int, userChoice: Boolean) -> Unit ) : IBaseItemVm { override val brVariableId = BR.vmSwitch override val layoutId = R.layout.item_switch val listener = CompoundButton.OnCheckedChangeListener { _, isChecked -> actionOnReceive.invoke(id, isChecked) } }
Di sini Anda dapat melihat di mana logika metode
onBindViewHolder () pergi . Android Databinding mengambilnya sendiri - sekarang semua tata letak kami didukung oleh model tampilan, dan itu dengan tenang akan memproses semua logika klik, animasi, kueri, dan hal-hal lainnya. Apa yang Anda pikirkan.
Binding Adapters akan melakukan pekerjaan ini dengan baik - memungkinkan Anda menghubungkan tampilan dengan data apa pun. juga, komunikasi dapat ditingkatkan berkat
databyding dua arah . Mungkin dia akan mem-flash salah satu artikel berikut, dalam contoh ini semuanya dapat dibuat lebih sederhana. Satu adaptor adaptor sudah cukup bagi kami:
@BindingAdapter("switchListener") fun setSwitchListener(sw: Switch, listener: CompoundButton.OnCheckedChangeListener) { sw.setOnCheckedChangeListener(listener) }
Setelah itu, ikat nilai variabel kami dengan
Item kami di dalam xml:
item_info.xml; item_switch.xml <?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"> <data> <import type="com.lfkekpoint.adapters.adapters.presentation.modules.bindableItemsSettings.InfoItem" /> <variable name="vmInfo" type="InfoItem" /> </data> <FrameLayout android:layout_width="match_parent" android:layout_height="56dp"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:layout_marginStart="28dp" android:text="@{vmInfo.title}" android:textColor="@color/black" android:textSize="20sp" tools:text="Balance" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical|end" android:layout_marginEnd="48dp" android:text="@{vmInfo.value}" tools:text="1000 $" /> </FrameLayout> </layout> <?xml version="1.0" encoding="utf-8"?> <layout 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"> <data> <import type="com.lfkekpoint.adapters.adapters.presentation.modules.bindableItemsSettings.SwitchItem" /> <variable name="vmSwitch" type="SwitchItem" /> </data> <FrameLayout android:layout_width="match_parent" android:layout_height="56dp"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:layout_marginStart="28dp" android:text="@{vmSwitch.title}" android:textColor="@color/black" android:textSize="20sp" tools:text="Send notifications" /> <Switch android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical|end" android:layout_marginEnd="48dp" app:switchListener="@{vmSwitch.listener}" tools:checked="true" /> </FrameLayout> </layout>
app: switchListener = "@ {vmSwitch.listener}" - pada baris ini kami menggunakan
BindingAdapter kami
* Catatan: Untuk alasan yang wajar, mungkin bagi sebagian orang kita menulis lebih banyak kode dalam xml - tetapi ini adalah masalah mengetahui pustaka Penyatuan Data Android. Ini melengkapi tata letak, membaca dengan cepat dan, pada prinsipnya, untuk sebagian besar menghilangkan pelat ketel. Saya pikir Google akan mengembangkan perpustakaan ini dengan baik, karena ini adalah yang pertama di tab Arsitektur di Android Jetpack. Cobalah untuk mengubah MVP ke MVVM di beberapa proyek - dan banyak yang mungkin terkejut.
Baiklah! .. Ah, kode di SettingsActivity:
SettingsActivity.kt... belum berubah, kecuali adaptornya berubah! =) Tetapi agar tidak melompati artikel:
class SettingsActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_settings) val adapter = BaseVmListAdapter() rView.layoutManager = LinearLayoutManager(this) rView.adapter = adapter adapter.add(InfoItem("User Name", "Leo Allford")) adapter.add(InfoItem("Balance", "350 $")) adapter.add(InfoItem("Tariff", "Business")) adapter.add(SwitchItem(1, "Send Notifications") { itemId, userChoice -> onCheck(itemId, userChoice) }) adapter.add(SwitchItem(2, "Send News on Email") { itemId, userChoice -> onCheck(itemId, userChoice) }) } private fun onCheck(itemId: Int, userChoice: Boolean) { when (itemId) { 1 -> Toast.makeText(this, "Notification now set as $userChoice", Toast.LENGTH_SHORT).show() 2 -> Toast.makeText(this, "Send news now set as $userChoice", Toast.LENGTH_SHORT).show() } } }
Ringkasan
Kami mendapat algoritme untuk membuat daftar dan alat untuk bekerja dengannya. Dalam kasus saya (saya hampir selalu menggunakan
Penyatuan Data ) semua persiapan dilakukan untuk menginisialisasi kelas dasar dalam folder, tata letak item dalam .xml dan kemudian mengikat ke variabel dalam .kt.
Mempercepat pengembanganUntuk pekerjaan yang lebih cepat, saya menggunakan
templat dari Apache untuk Android Studio - dan menulis
templat saya dengan
demonstrasi kecil
tentang cara kerjanya. Saya sangat berharap bahwa seseorang akan berguna. Harap dicatat bahwa ketika bekerja, Anda perlu memanggil templat dari folder root proyek - ini dilakukan karena parameter
applicationId proyek dapat berbohong kepada Anda jika Anda mengubahnya di Gradle. Tapi
packageName tidak bisa
dibodohi dengan mudah, yang saya gunakan. Bahasa yang tersedia tentang templat dapat dibaca di tautan di bawah ini
Referensi / Media
1.
Perkembangan Android modern: Android Jetpack, Kotlin, dan lainnya (Google I / O 2018, 40 m). - sebuah panduan singkat tentang apa yang sedang populer saat ini, dari sini juga akan menjadi jelas secara umum bagaimana RecyclerView dikembangkan;
2.
Droidcon NYC 2016 - Radical RecyclerView, 36 m. - Laporan terperinci tentang RecyclerView dari
Lisa Wray ;
3.
Buat Daftar dengan RecyclerView - dokumentasi resmi
4.
Antarmuka vs. kelas5.
Format Template Android IDE ,
Templating total ,
manual FreeMarker - pendekatan yang nyaman, yang dalam kerangka artikel ini akan membantu untuk dengan cepat membuat file yang diperlukan untuk bekerja dengan daftar
6.
Kode untuk artikel (ada nama kelas yang sedikit berbeda, hati-hati),
template untuk pekerjaan dan
video, cara bekerja dengan template7. Versi
bahasa Inggris artikel