لعرض قائمة البيانات التي نستخدمها RecyclerView
(- شكرا لك ، كاب!). إنه يعرف الكثير من الأشياء من العلبة وغيرها من blablabs المعروفة. ولكن هناك الكثير من الألم معه. لا أحد يحب كتابة نفس الرمز المعياري. وأنا لست حقًا ...

نبذة تاريخية عن المؤامرة "تقليل الرمز قليلاً":

على سبيل المثال ، تم إنشاء فئة بيانات بسيطة Person (): بالاسم الأول واسم العائلة والبريد الإلكتروني. توفر البريد والكلب.
لعرض قائمة من الناس، يجب عليك إنشاء RecyclerView.Adapter
و RecyclerView.ViewHolder
، فإن معظم الذين + كود هو نفسه.
Adapter
ViewHolder
-, . , , ViewHolder
, .
Adapter
ViewHolder
, .
RecyclerView.Adapter<RecyclerView.ViewHolder>
Adapter . , .class ClassicAdapter : RecyclerView.Adapter<ClassicHolder>() {
private val viewModel = PersonItemViewModel()
private val data: List<Person>
get() = viewModel.data
fun setData(persons: List<Person>) {
viewModel.data = persons
notifyDataSetChanged()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ClassicHolder =
ClassicHolder.create(parent)
override fun getItemCount(): Int = data.size
override fun onBindViewHolder(holder: ClassicHolder, position: Int) {
holder.bind(viewModel, position)
}
}
ViewHolder MVVM.class ClassicHolder(private val binding: ItemPersonBinding) : RecyclerView.ViewHolder(binding.root) {
fun bind(viewModel: PersonItemViewModel, position: Int) {
binding.setVariable(BR.viewModel, viewModel)
binding.setVariable(BR.position, position)
binding.executePendingBindings()
}
companion object {
fun create(parent: ViewGroup): ClassicHolder {
val inflater = LayoutInflater.from(parent.context)
val binding: ItemPersonBinding =
DataBindingUtil.inflate(inflater, R.layout.item_person, parent, false)
return ClassicHolder(binding)
}
}
}
item_person.xml binding-: ViewModel Position - RecyclerView.<?xml version="1.0" encoding="utf-8"?>
<layout>
<data>
<variable
name="position"
type="Integer" />
<variable
name="viewModel"
type="plus.yeti.prostoadapter.ui.main.PersonItemViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout>
<TextView
android:text="@{viewModel.getName(position)}"
... />
<TextView
android:text="@{viewModel.getEmail(position)}"
.../>
<ImageView
app:visible="@{viewModel.hasDog(position)}"
.../>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
PersonItemViewModel .class PersonItemViewModel : ProstoViewModel<Person>() {
override var data: List<Person> = emptyList()
fun getName(position: Int) = data[position].lastName + ", " + data[position].firstName
fun getEmail(position: Int) = data[position].email
fun hasDog(position: Int): Boolean = data[position].hasDog
}
ProstoAdapter
ProstoHolder
, Adapter
ViewHolder
, .
ProstoViewModel
. , ProstoViewModel
, , , . ViewModel
-:
abstract class ProstoViewModel<T>: ViewModel() {
abstract var data: List<T>
}
ProstoHolder
open class ProstoHolder<TBinding : ViewDataBinding>(val binding: TBinding) : RecyclerView.ViewHolder(binding.root) {
open fun <TData, TViewModel : ProstoViewModel<TData>> bind(viewModel: TViewModel, position: Int) {
binding.setVariable(BR.viewModel, viewModel)
binding.setVariable(BR.position, position)
binding.executePendingBindings()
}
companion object {
fun <TBinding : ViewDataBinding> create(parent: ViewGroup, layoutId: Int): ProstoHolder<TBinding> {
val inflater = LayoutInflater.from(parent.context)
val binding: TBinding = DataBindingUtil.inflate(inflater, layoutId, parent, false)
return ProstoHolder(binding)
}
}
}
, , ProstoAdapter
:
abstract class ProstoAdapter<TBinding : ViewDataBinding, TData> : RecyclerView.Adapter<ProstoHolder<TBinding>>() {
abstract val viewModel: ProstoViewModel<TData>
abstract val layoutId: Int
private var dataSize: Int = 0
open fun setData(data: List<TData>) {
this.dataSize = data.size
viewModel.data = data
notifyDataSetChanged()
}
open var onBind: ((ProstoHolder<TBinding>) -> Unit)? = null
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ProstoHolder<TBinding> =
ProstoHolder.create(parent, layoutId)
override fun getItemCount(): Int = dataSize
override fun onBindViewHolder(holder: ProstoHolder<TBinding>, position: Int) {
holder.bind(viewModel, position)
onBind?.invoke(holder)
}
}
Adapter
-a ViewModel
c , item's layout id
Binding-, layout
-, item-.
, :)
class MainFragment : Fragment() {
private val adapter =
object : ProstoAdapter<ItemPersonBinding, Person>() {
override val viewModel = PersonItemViewModel()
override val layoutId = R.layout.item_person
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
mainRecyclerView.adapter = adapter
}
fun setNewPersonList(persons: List<Person>){
adapter.setData(personList)
}
}
4 .
github.com/klukwist/Prosto
ViewHolder-.
:)