A1m*_*A1m 65 android android-viewbinding
我可以使用 ViewBindings 来替换findViewById
这个典型的RecyclerView.Adapter
初始化代码吗?我无法binding
在对象中设置val,因为每个单元格的 ViewHolders 都不同。
class CardListAdapter(private val cards: LiveData<List<Card>>) : RecyclerView.Adapter<CardListAdapter.CardViewHolder>() {
class CardViewHolder(val cardView: View) : RecyclerView.ViewHolder(cardView)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CardViewHolder {
val binding = CardBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return CardViewHolder(binding.root)
}
override fun onBindViewHolder(holder: CardViewHolder, position: Int) {
val title = holder.cardView.findViewById<TextView>(R.id.title)
val description = holder.cardView.findViewById<TextView>(R.id.description)
val value = holder.cardView.findViewById<TextView>(R.id.value)
// ...
}
Run Code Online (Sandbox Code Playgroud)
Som*_*mar 136
您需要做的是将生成的绑定类对象传递给持有者类构造函数。在下面的示例中,我有项目的row_payment
XML 文件,RecyclerView
生成的类是RowPaymentBinding
这样的
class PaymentAdapter(private val paymentList: List<PaymentBean>) : RecyclerView.Adapter<PaymentAdapter.PaymentHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PaymentHolder {
val itemBinding = RowPaymentBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return PaymentHolder(itemBinding)
}
override fun onBindViewHolder(holder: PaymentHolder, position: Int) {
val paymentBean: PaymentBean = paymentList[position]
holder.bind(paymentBean)
}
override fun getItemCount(): Int = paymentList.size
class PaymentHolder(private val itemBinding: RowPaymentBinding) : RecyclerView.ViewHolder(itemBinding.root) {
fun bind(paymentBean: PaymentBean) {
itemBinding.tvPaymentInvoiceNumber.text = paymentBean.invoiceNumber
itemBinding.tvPaymentAmount.text = paymentBean.totalAmount
}
}
}
Run Code Online (Sandbox Code Playgroud)
此外,请确保RecyclerView.ViewHolder(itemBinding.root)
通过访问传递的绑定类对象将根视图传递给 Viewholder 的父类。
我写了一个简单且可重用的:
class ViewBindingVH constructor(val binding: ViewBinding) :
RecyclerView.ViewHolder(binding.root) {
companion object {
inline fun create(
parent: ViewGroup,
crossinline block: (inflater: LayoutInflater, container: ViewGroup, attach: Boolean) -> ViewBinding
) = ViewBindingVH(block(LayoutInflater.from(parent.context), parent, false))
}
}
class CardAdapter : RecyclerView.Adapter<ViewBindingVH>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewBindingVH {
return ViewBindingVH.create(parent, CardBinding::inflate)
}
override fun onBindViewHolder(holder: ViewBindingVH, position: Int) {
(holder.binding as CardBinding).apply {
//bind model to view
title.text = "some text"
descripiton.text = "some text"
}
}
}
Run Code Online (Sandbox Code Playgroud)
您可以像这样使用视图绑定:
package com.example.kotlinprogramming.adapter
import android.content.Context
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.example.kotlinprogramming.data.HobbiesData
import com.example.kotlinprogramming.databinding.ItemHobbieBinding
class HobbiesAdapter(var context: Context, var hobbiesList: List<HobbiesData>) :
RecyclerView.Adapter<HobbiesAdapter.HobbiesViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): HobbiesViewHolder {
val view = ItemHobbieBinding.inflate(LayoutInflater.from(context) , parent,false)
return HobbiesViewHolder(view)
}
override fun onBindViewHolder(holder: HobbiesViewHolder, position: Int) {
val hobbie = hobbiesList.get(position)
holder.viewBinding.tvHobbie.text = hobbie.title
}
inner class HobbiesViewHolder(var viewBinding: ItemHobbieBinding) : RecyclerView.ViewHolder(viewBinding.root) {
}
override fun getItemCount(): Int {
return hobbiesList.size
}
}
Run Code Online (Sandbox Code Playgroud)
这是 item_hobbies.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_margin="12dp"
android:layout_height="wrap_content"
>
<TextView
android:id="@+id/tvHobbie"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="8dp"
android:gravity="center"
android:textSize="30sp"
tools:text="Hobbie1"
/>
</androidx.cardview.widget.CardView>
Run Code Online (Sandbox Code Playgroud)
附加binding
到 ViewHolder 而不是 View
class CardViewHolder(val binding: CardBinding) : RecyclerView.ViewHolder(binding.root)
Run Code Online (Sandbox Code Playgroud)
你传递绑定,绑定传递binding.root
给RecyclerView.ViewHolder(binding.root)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CardViewHolder {
val binding = CardBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return CardViewHolder(binding)
}
Run Code Online (Sandbox Code Playgroud)
然后通过以下方式访问任何地方:
holder.binding.title
Run Code Online (Sandbox Code Playgroud)
如果你同意反思,我有一个更简单的方法来做到这一点。只需调用 ViewGroup.toBinding() 即可获取所需的绑定对象。但既然我们谈论的是反射,请记住你必须修改你的 proguard 规则以使其即使对于 proguard 也能工作。
// inside adapter
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return MainViewHolder(parent.toBinding())
}
// ViewHolder
class MainViewHolder(private val binding: AdapterMainBinding) :
RecyclerView.ViewHolder(binding.root) {
fun bind(data: String) {
binding.name.text = data
}
}
// The magic reflection can reused everywhere.
inline fun <reified V : ViewBinding> ViewGroup.toBinding(): V {
return V::class.java.getMethod(
"inflate",
LayoutInflater::class.java,
ViewGroup::class.java,
Boolean::class.java
).invoke(null, LayoutInflater.from(context), this, false) as V
}
Run Code Online (Sandbox Code Playgroud)
我把所有这些都放到了一个开源项目中,你也可以看看。不仅适用于Adapter的使用,还包括Activity和Fragment的使用。如果您有任何意见,请告诉我。谢谢。
https://github.com/Jintin/BindingExtension
归档时间: |
|
查看次数: |
27103 次 |
最近记录: |