DataBinding:如何使用 Kotlin 中的泛型创建具有多个 ViewHolder(多个布局)的 Recyclerview
Posted
技术标签:
【中文标题】DataBinding:如何使用 Kotlin 中的泛型创建具有多个 ViewHolder(多个布局)的 Recyclerview【英文标题】:DataBinding: How to create Recyclerview with multiple ViewHolder (multiple layout) using generics in Kotlin 【发布时间】:2021-06-19 22:23:33 【问题描述】:我有下面的代码,我在具有多个 ViewHolders 的 RecyclerView 中使用泛型,我正在尝试使用 DataBinding 升级此代码,我正在寻找具有多个 ViewHolders 的 RecyclerView 并在其中使用 DataBinding。
class JumbledWordAdapter(
var items: List<JumbledWord>
) : RecyclerView.Adapter<RecyclerView.ViewHolder>()
companion object
const val TYPE_PLACE_HOLDER = 0
const val TYPE_ANSWER = 1
const val INVALID = -1
var selectedItemPos = INVALID
override fun getItemViewType(position: Int) = (items[position].currentType)//choose layout type
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder
return when (viewType)
TYPE_PLACE_HOLDER ->
PlaceHolderViewHolder(
LayoutInflater.from(parent.context)
.inflate(R.layout.lyt_jumbled_word_place_holder_item, parent, false)
)
TYPE_ANSWER ->
AnswerViewHolder(
LayoutInflater.from(parent.context)
.inflate(R.layout.lyt_jumbled_word_answer_item, parent, false)
)
else -> throw IllegalArgumentException("Invalid view type")
override fun getItemCount(): Int = items.size
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int)
when (holder)
is PlaceHolderViewHolder -> holder.bind(position)
is AnswerViewHolder -> holder.bind(position)
inner class PlaceHolderViewHolder(val view: View) : RecyclerView.ViewHolder(view)
private val cardParent: MaterialCardView = view.findViewById(R.id.cardParent)
fun bind(position: Int)
cardParent.isSelected = items[position].isSelected
cardParent.setOnClickListener
//some code.
inner class AnswerViewHolder(val view: View) : RecyclerView.ViewHolder(view)
private val cardParent: MaterialCardView = view.findViewById(R.id.cardParent)
private val tvLetter: TextView = view.findViewById(R.id.tvLetter)
fun bind(position: Int)
tvLetter.text = items[position].answer
cardParent.setOnClickListener
//some code.
需要在这个适配器类中实现Databinding。
【问题讨论】:
【参考方案1】:我认为 DataBinding 应该在 ViewHolder 中隔离,因为将值绑定到视图不是 Adapter 的责任。
所以我写了这个:
class JumbledWordAdapter(
val items: List<ItemListFragment.JumbledWord>
) : RecyclerView.Adapter<RecyclerView.ViewHolder>()
companion object
const val TYPE_PLACE_HOLDER = 0
const val TYPE_ANSWER = 1
const val INVALID = -1
var selectedItemPos = INVALID
override fun getItemViewType(position: Int) = (items[position].currentType)//choose layout type
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder
return when (viewType)
TYPE_PLACE_HOLDER -> PlaceHolderViewHolder(parent)
TYPE_ANSWER -> AnswerViewHolder(parent)
else -> throw IllegalArgumentException("Invalid view type")
override fun getItemCount(): Int = items.size
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int)
when (holder)
is PlaceHolderViewHolder -> holder.bind(position)
is AnswerViewHolder -> holder.bind(position)
inner class PlaceHolderViewHolder private constructor(
val binding: LytJumbledWordPlaceHolderItemBinding
) : RecyclerView.ViewHolder(binding.root)
constructor(parent: ViewGroup) : this(
LytJumbledWordPlaceHolderItemBinding.inflate(
LayoutInflater.from(parent.context),
parent,
false
)
)
init
// set click listeners at view-holder initialize time
binding.cardParent.setOnClickListener
if (adapterPosition != RecyclerView.NO_POSITION)
//some code.
fun bind(position: Int)
binding.cardParent.isSelected = items[position].isSelected
inner class AnswerViewHolder private constructor(
val binding: LytJumbledWordAnswerItemBinding
) : RecyclerView.ViewHolder(binding.root)
constructor(parent: ViewGroup) : this(
LytJumbledWordAnswerItemBinding.inflate(
LayoutInflater.from(parent.context),
parent,
false
)
)
init
// set click listeners at view-holder initialize time
binding.cardParent.setOnClickListener
if (adapterPosition != RecyclerView.NO_POSITION)
//some code.
fun bind(position: Int)
binding.tvLetter.text = items[position].answer
PS:我们还应该在viewholder初始化时间设置clickListeners。 (不在绑定时间内)
【讨论】:
adapterPosition 已弃用。我可以使用 getBindingAdapterPosition() 吗? @Alfin 我正在使用最新的稳定版本的 recyclerview (1.1.0)。如果您使用的是不稳定版本,是的。你可以改用getBindingAdapterPosition()
。以上是关于DataBinding:如何使用 Kotlin 中的泛型创建具有多个 ViewHolder(多个布局)的 Recyclerview的主要内容,如果未能解决你的问题,请参考以下文章
使用 Kotlin Multiplatform Mobile (KMM) 的多平台应用程序中的 DataBinding 错误
DataBinding 和 LiveData :两种实现(Kotlin 和 Java),不能使 Java impl 工作