हमारे द्वारा उपयोग किए जाने वाले डेटा की सूची प्रदर्शित करने के लिए RecyclerView
(- धन्यवाद, कैप!)। वह बॉक्स और अन्य प्रसिद्ध ब्लोबैब्स से बहुत सी चीजें जानता है। लेकिन उसके साथ बहुत दर्द है। कोई भी एक ही बॉयलरप्लेट कोड लिखना पसंद नहीं करता है। और मैं वास्तव में नहीं हूँ ...

साजिश का एक संक्षिप्त इतिहास "कोड को थोड़ा कम करें":

उदाहरण के लिए, एक साधारण डेटा वर्ग व्यक्ति () बनाया गया था: पहला नाम, अंतिम नाम, ईमेल। मेल और कुत्ते की उपलब्धता।
लोगों की सूची प्रदर्शित करने के लिए, आपको बनाना होगा 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-.
:)