首页 > 解决方案 > 为什么 UI 有时使用 recyclerview 和数据绑定不更新?

问题描述

我正在使用带有 Room、LiveData、带有 ListAdapter 和数据绑定的 RecyclerView 的 MVVM 创建一个待办事项应用程序。当我检查一个项目时,它会跳到列表的底部(按不完整排序,然后完成)。我还为已完成的项目使用了不同的布局,其中文本变为斜体并变灰。通常当我选中一个框时,它会跳下来并变成灰色/斜体,但有时它会保持黑色。我怎样才能找到这个问题,或者它可能是数据绑定库的问题?

// ToDoItemAdapter.kt

const val ITEM_UNCHECKED = 0
const val ITEM_CHECKED = 1

class ToDoItemAdapter(private val onCheckboxClick: (ToDoItem) -> Unit, private val onCardClick: (ToDoItem) -> Unit): ListAdapter<ToDoItem, RecyclerView.ViewHolder>(ToDoItemDiffCallback()) {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        return when (viewType) {
            ITEM_CHECKED -> ViewHolderChecked.from(parent)
            else -> ViewHolderUnchecked.from(parent)
        }
    }

    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        when (holder) {
            is ViewHolderChecked -> {
                val toDoItem = getItem(position)
                holder.bind(toDoItem, onCheckboxClick, onCardClick)
            }
            is ViewHolderUnchecked -> {
                val toDoItem = getItem(position)
                holder.bind(toDoItem, onCheckboxClick, onCardClick)
            }
        }
    }

    override fun getItemViewType(position: Int): Int {
        val toDoItem = getItem(position)
        return when (toDoItem.completed) {
            true -> ITEM_CHECKED
            false -> ITEM_UNCHECKED
        }
    }

    class ViewHolderChecked private constructor(private val binding: ChecklistItemCheckedBinding)
        : RecyclerView.ViewHolder(binding.root) {

        fun bind(toDoItem: ToDoItem, onCheckboxClick: (ToDoItem) -> Unit, onCardClick: (ToDoItem) -> Unit) {
            binding.todoItem = toDoItem
            binding.checkboxCompleted.setOnClickListener {
                onCheckboxClick(toDoItem)
            }
            binding.cardTodo.setOnClickListener {
                onCardClick(toDoItem)
            }
            binding.executePendingBindings()
        }

        companion object {
            fun from(parent: ViewGroup): ViewHolderChecked {
                val layoutInflater = LayoutInflater.from(parent.context)
                return ViewHolderChecked(ChecklistItemCheckedBinding.inflate(layoutInflater, parent, false))
            }
        }
    }

在适配器中,当单击复选框时,它会在视图模型中运行一个函数:

fun toggleCheckbox(toDoItem: ToDoItem) {
    toDoItem.completed = !toDoItem.completed
    update(toDoItem)
}

update(toDoItem) 调用挂起函数,基本上通过后台线程上的存储库更新 Room 数据库中的数据。

在片段中,我将绑定设置为等于视图模型,设置生命周期所有者,设置适配器,然后在 allToDoItems 列表上设置观察者:

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                              savedInstanceState: Bundle?): View? {
    binding.checklistViewModel = checklistViewModel
    binding.lifecycleOwner = this
    val adapter = ToDoItemAdapter(onCheckboxClickHandler, onCardClickHandler)
    binding.itemsList.adapter = adapter
    checklistViewModel.allToDoItems.observe(viewLifecycleOwner, Observer { allItems ->
        allItems?.let {
            adapter.submitList(allItems.sortedWith(compareBy(
                {it.completed},
                {it.description}))
            )
        }
    })
    return binding.root
}

标签: androidkotlinandroid-recyclerviewandroid-databinding

解决方案


推荐阅读