onBindViewHolder android kotlin 中发生奇怪的行为
Strange behaviour happen in onBindViewHolder android kotlin
嘿,我在 android kotlin 工作。我在 reyclerview 工作。我想在我的项目中进行单一选择。我尝试了一些工作正常的代码。
OptionsViewAdapter.kt
class OptionsViewAdapter : ListAdapter<ProductVariant, OptionsViewHolder>(PRODUCT_COMPARATOR) {
private var selectedItemPosition: Int = 0
companion object {
private val PRODUCT_COMPARATOR = object : DiffUtil.ItemCallback<ProductVariant>() {
override fun areItemsTheSame(
oldItem: ProductVariant,
newItem: ProductVariant
): Boolean {
return oldItem == newItem
}
override fun areContentsTheSame(
oldItem: ProductVariant,
newItem: ProductVariant
): Boolean {
return oldItem == newItem
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): OptionsViewHolder {
return OptionsViewHolder.bindView(parent)
}
override fun onBindViewHolder(holder: OptionsViewHolder, position: Int) {
holder.binding.root.setOnClickListener {
selectedItemPosition = holder.bindingAdapterPosition
notifyAdapter()
}
val drawableColor = if (selectedItemPosition == position)
R.drawable.options_item_selected_background
else
R.drawable.options_item_default_background
holder.binding.root.background =
ContextCompat.getDrawable(holder.binding.root.context, drawableColor)
holder.bindItem(getItem(position), position)
}
fun notifyAdapter() {
notifyDataSetChanged()
}
}
OptionsViewHolder.kt
class OptionsViewHolder(
val binding: OptionsItemLayoutBinding,
) : RecyclerView.ViewHolder(binding.root) {
companion object {
fun bindView(parent: ViewGroup): OptionsViewHolder {
return OptionsViewHolder(
OptionsItemLayoutBinding.inflate(
LayoutInflater.from(parent.context),
parent,
false
)
)
}
}
fun bindItem(item: ProductVariant?, position: Int) {
}
}
Video 单击即可正常工作。
当我在 bindItem
中移动 onBindViewHolder
代码时,它不起作用。谁能指导我为什么会这样。
对
OptionsViewAdapter.kt
class OptionsViewAdapter : ListAdapter<ProductVariant, OptionsViewHolder>(PRODUCT_COMPARATOR) {
companion object {
private val PRODUCT_COMPARATOR = object : DiffUtil.ItemCallback<ProductVariant>() {
override fun areItemsTheSame(
oldItem: ProductVariant,
newItem: ProductVariant
): Boolean {
return oldItem == newItem
}
override fun areContentsTheSame(
oldItem: ProductVariant,
newItem: ProductVariant
): Boolean {
return oldItem == newItem
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): OptionsViewHolder {
return OptionsViewHolder.bindView(parent)
}
override fun onBindViewHolder(holder: OptionsViewHolder, position: Int) {
holder.bindItem(getItem(position), position ,::notifyAdapter)
}
fun notifyAdapter() {
notifyDataSetChanged()
}
}
OptionsViewHolder.kt
class OptionsViewHolder(
val binding: OptionsItemLayoutBinding,
) : RecyclerView.ViewHolder(binding.root) {
private var selectedItemPosition: Int = 0
companion object {
fun bindView(parent: ViewGroup): OptionsViewHolder {
return OptionsViewHolder(
OptionsItemLayoutBinding.inflate(
LayoutInflater.from(parent.context),
parent,
false
)
)
}
}
fun bindItem(
item: ProductVariant?,
position: Int,
onAdapterChange: () -> Unit
) {
binding.root.setOnClickListener {
selectedItemPosition = position
onAdapterChange()
}
val drawableColor = if (selectedItemPosition == position)
R.drawable.options_item_selected_background
else
R.drawable.options_item_default_background
binding.root.background =
ContextCompat.getDrawable(binding.root.context, drawableColor)
}
}
单击 video 无效。
即使您在 bindItem()
函数中传递方法引用 notifyAdapter()
,您也没有在 OnClickListener
中调用它,这就是它不起作用的原因。
您将 selectedItemPosition
移到了 ViewHolder class 中,因此对于 ViewHolder class 的每个实例,您都有一个此 属性 的单独副本,所以您不是单击任何一个列表项时不再影响列表中的其他项。
通过使视图持有者 class 成为适配器的 inner class
可以更容易地实现,这样它就可以直接修改适配器的 selectedItemPosition
属性。我会给 属性 一个自定义的 setter,这样您就可以自动将更改通知适配器,而不必使用单独的函数调用。您还可以让它专门通知适配器哪两个行项目发生了变化,而不是整个数据集(效率更高,并且通过在 属性 setter 中执行此操作,您可以访问新旧行位置轻松地放在一个地方——field
和 value
)。
private var selectedItemPosition: Int = 0
set(value) {
val oldPos = field
field = value
notifyItemChanged(oldPos)
notifyItemChanged(value)
}
嘿,我在 android kotlin 工作。我在 reyclerview 工作。我想在我的项目中进行单一选择。我尝试了一些工作正常的代码。
OptionsViewAdapter.kt
class OptionsViewAdapter : ListAdapter<ProductVariant, OptionsViewHolder>(PRODUCT_COMPARATOR) {
private var selectedItemPosition: Int = 0
companion object {
private val PRODUCT_COMPARATOR = object : DiffUtil.ItemCallback<ProductVariant>() {
override fun areItemsTheSame(
oldItem: ProductVariant,
newItem: ProductVariant
): Boolean {
return oldItem == newItem
}
override fun areContentsTheSame(
oldItem: ProductVariant,
newItem: ProductVariant
): Boolean {
return oldItem == newItem
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): OptionsViewHolder {
return OptionsViewHolder.bindView(parent)
}
override fun onBindViewHolder(holder: OptionsViewHolder, position: Int) {
holder.binding.root.setOnClickListener {
selectedItemPosition = holder.bindingAdapterPosition
notifyAdapter()
}
val drawableColor = if (selectedItemPosition == position)
R.drawable.options_item_selected_background
else
R.drawable.options_item_default_background
holder.binding.root.background =
ContextCompat.getDrawable(holder.binding.root.context, drawableColor)
holder.bindItem(getItem(position), position)
}
fun notifyAdapter() {
notifyDataSetChanged()
}
}
OptionsViewHolder.kt
class OptionsViewHolder(
val binding: OptionsItemLayoutBinding,
) : RecyclerView.ViewHolder(binding.root) {
companion object {
fun bindView(parent: ViewGroup): OptionsViewHolder {
return OptionsViewHolder(
OptionsItemLayoutBinding.inflate(
LayoutInflater.from(parent.context),
parent,
false
)
)
}
}
fun bindItem(item: ProductVariant?, position: Int) {
}
}
Video 单击即可正常工作。
当我在 bindItem
中移动 onBindViewHolder
代码时,它不起作用。谁能指导我为什么会这样。
对
OptionsViewAdapter.kt
class OptionsViewAdapter : ListAdapter<ProductVariant, OptionsViewHolder>(PRODUCT_COMPARATOR) {
companion object {
private val PRODUCT_COMPARATOR = object : DiffUtil.ItemCallback<ProductVariant>() {
override fun areItemsTheSame(
oldItem: ProductVariant,
newItem: ProductVariant
): Boolean {
return oldItem == newItem
}
override fun areContentsTheSame(
oldItem: ProductVariant,
newItem: ProductVariant
): Boolean {
return oldItem == newItem
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): OptionsViewHolder {
return OptionsViewHolder.bindView(parent)
}
override fun onBindViewHolder(holder: OptionsViewHolder, position: Int) {
holder.bindItem(getItem(position), position ,::notifyAdapter)
}
fun notifyAdapter() {
notifyDataSetChanged()
}
}
OptionsViewHolder.kt
class OptionsViewHolder(
val binding: OptionsItemLayoutBinding,
) : RecyclerView.ViewHolder(binding.root) {
private var selectedItemPosition: Int = 0
companion object {
fun bindView(parent: ViewGroup): OptionsViewHolder {
return OptionsViewHolder(
OptionsItemLayoutBinding.inflate(
LayoutInflater.from(parent.context),
parent,
false
)
)
}
}
fun bindItem(
item: ProductVariant?,
position: Int,
onAdapterChange: () -> Unit
) {
binding.root.setOnClickListener {
selectedItemPosition = position
onAdapterChange()
}
val drawableColor = if (selectedItemPosition == position)
R.drawable.options_item_selected_background
else
R.drawable.options_item_default_background
binding.root.background =
ContextCompat.getDrawable(binding.root.context, drawableColor)
}
}
单击 video 无效。
即使您在 bindItem()
函数中传递方法引用 notifyAdapter()
,您也没有在 OnClickListener
中调用它,这就是它不起作用的原因。
您将 selectedItemPosition
移到了 ViewHolder class 中,因此对于 ViewHolder class 的每个实例,您都有一个此 属性 的单独副本,所以您不是单击任何一个列表项时不再影响列表中的其他项。
通过使视图持有者 class 成为适配器的 inner class
可以更容易地实现,这样它就可以直接修改适配器的 selectedItemPosition
属性。我会给 属性 一个自定义的 setter,这样您就可以自动将更改通知适配器,而不必使用单独的函数调用。您还可以让它专门通知适配器哪两个行项目发生了变化,而不是整个数据集(效率更高,并且通过在 属性 setter 中执行此操作,您可以访问新旧行位置轻松地放在一个地方——field
和 value
)。
private var selectedItemPosition: Int = 0
set(value) {
val oldPos = field
field = value
notifyItemChanged(oldPos)
notifyItemChanged(value)
}