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 中执行此操作,您可以访问新旧行位置轻松地放在一个地方——fieldvalue)。

private var selectedItemPosition: Int = 0
    set(value) {
        val oldPos = field
        field = value
        notifyItemChanged(oldPos)
        notifyItemChanged(value)
    }