以编程方式向 RecyclerView 项目添加一些视图会创建一个已知错误

Adding Some View to RecyclerView item programmatically creates an known bug

所以我正在创建一个待办事项应用程序,用户可以在其中设置优先级,优先级星号是通过绑定适配器以编程方式添加的,但是当滚动任务回收器视图时,星号为零的任务也显示星号,其中检查日志显示为零星星。此外,仅当我滚动到带星标的项目然后开始严格滚动时才会出现此错误

  1. 应用刚刚启动

  1. 已滚动到带有任务星标的项目

  1. 严格滚动后

我已尝试在每次更新项目时创建新的 ArrayList

片段代码:

viewModel.taskCategory.observe(viewLifecycleOwner, Observer { taskCategoryPair ->
            taskCategoryPair?.let {
                Log.i("HomeFragment","Submitting New List")
                viewModel.filterDataFinish()
                adaptor.submitList(it)
            }
        })

RecyclerView 绑定代码:

 RecyclerView.ViewHolder(binding.root) {
        fun bind(
            task: ToDo,
            category: Category,
            clickListener: MiscellaneousUtils.GetIdFromClick
        ) {
            binding.task = task
            binding.category = category
            binding.clickListener = clickListener
            binding.onCheckChangeListener = categorizedTasksClickListeners

            binding.root.setOnLongClickListener {
                categorizedTasksClickListeners.onLongClickItem(adapterPosition,it)
                true
            }

            binding.executePendingBindings()
        }

添加星星的BindingAdapter函数:

@BindingAdapter("app:setPriority")
fun LinearLayoutCompat.setPriority(task: ToDo) {
    if (task.priorityStars == 0)
        return

    val previousStarContainer = findViewWithTag<LinearLayout>("starContainerLayout")

    if (previousStarContainer != null) {
        removeView(previousStarContainer)
    }

    val starContainer = LinearLayout(context)
    starContainer.tag = "starContainerLayout"
    starContainer.layoutParams = LinearLayoutCompat.LayoutParams(
        ViewGroup.LayoutParams.WRAP_CONTENT,
        ViewGroup.LayoutParams.WRAP_CONTENT
    )

    for (count in 1..task.priorityStars) {
        val starView = ImageView(context)
        starView.setImageResource(R.drawable.task_star)
        starView.layoutParams = LinearLayoutCompat.LayoutParams(
            ViewGroup.LayoutParams.WRAP_CONTENT,
            ViewGroup.LayoutParams.WRAP_CONTENT
        )
        starContainer.addView(starView)
    }
    addView(starContainer)

}

Recycler 回收视图 :) - 它使用相同的视图来显示多个数据!这意味着视图可用于显示带有星星的对象 - 所以在 onBindViewHolder 上显示星星。然后相同的视图(现在有星星)将用于显示不同的对象(没有星星对象)——这意味着在 onBindViewHolder 上你现在需要隐藏星星,我敢打赌你没有; )

正如我所说,如果你没有星星,你就不会删除之前的开始:

if (task.priorityStars == 0)
        return

将您的代码更改为:

@BindingAdapter("app:setPriority")
fun LinearLayoutCompat.setPriority(task: ToDo) {
    val previousStarContainer = findViewWithTag<LinearLayout>("starContainerLayout")

    if (previousStarContainer != null) {
        removeView(previousStarContainer)
    }

    if (task.priorityStars == 0)
        return

    val starContainer = LinearLayout(context)
    starContainer.tag = "starContainerLayout"
    starContainer.layoutParams = LinearLayoutCompat.LayoutParams(
        ViewGroup.LayoutParams.WRAP_CONTENT,
        ViewGroup.LayoutParams.WRAP_CONTENT
    )

    for (count in 1..task.priorityStars) {
        val starView = ImageView(context)
        starView.setImageResource(R.drawable.task_star)
        starView.layoutParams = LinearLayoutCompat.LayoutParams(
            ViewGroup.LayoutParams.WRAP_CONTENT,
            ViewGroup.LayoutParams.WRAP_CONTENT
        )
        starContainer.addView(starView)
    }
    addView(starContainer)

}