RecyclerView 不更新屏幕

RecyclerView does not update the screen

我正在尝试通过按钮添加项目。

我用了ListAdapterDiffUtil

然而,当按下按钮时,第一个项目被更新,但之后屏幕没有更新。

我用 AdapterDiffUtil 试过 debugging

我通过适配器中的currentList检查了List是否submitted,但是断点只对第一个项目有效,不会为项目停止之后添加。

DiffUtil中,我们确认break point根本不起作用。

我写错了什么代码?


片段

override fun onCreateView(
    inflater: LayoutInflater, container: ViewGroup?,
    savedInstanceState: Bundle?
): View? {
    _binding = FragmentWriteRoutine2Binding.inflate(inflater, container, false)

    adapter = DetailAdapter()

    binding.apply {
        rv.adapter = adapter
        rv.itemAnimator = null
        header.add.setOnClickListener {
            vm.addDetail()
        }
        header.delete.setOnClickListener {
            vm.deleteDetail()
        }
    }
    return binding.root
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    vm.items.observe(viewLifecycleOwner) { newList ->
        adapter.submitList(newList)
    }
}

RoutineItem

sealed class RoutineItem(
    val id: String,
) {
    class Header(
        id: String = UUID.randomUUID().toString(),
        val workout: String,
        val unit: String,
    ) : RoutineItem(id)

    class Detail(
        id: String = UUID.randomUUID().toString(),
        val set: Int,
        var weight: String = "",
        var reps: String = "",
    ) : RoutineItem(id)
}

适配器

class DetailAdapter
    : ListAdapter<RoutineItem, DetailAdapter.ViewHolder>(RoutineDiffCallback()) {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        return ViewHolder(
            ItemRoutineDetailBinding.inflate(
                LayoutInflater.from(parent.context),
                parent,
                false
            )
        )
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val cur = currentList
    }

    inner class ViewHolder(val binding: ItemRoutineDetailBinding) : RecyclerView.ViewHolder(binding.root) {
        fun bind(item: RoutineItem.Detail) {

        }
    }
}

DiffUtilCallback

class DetailDiffCallback : DiffUtil.ItemCallback<RoutineItem>() {
    override fun areItemsTheSame(
        oldItem: RoutineItem,
        newItem: RoutineItem
    ): Boolean = (oldItem.id == newItem.id)

    override fun areContentsTheSame(
        oldItem: RoutineItem,
        newItem: RoutineItem
    ): Boolean = (oldItem == newItem)
}

因为您没有使用 data classes 作为您的 Header 和 Detail classes,它们的 equals() 函数不适合在 == 中使用你的DiffUtil.ItemCallbackdata class 会自动比较其在 equals 中的所有构造函数属性,但常规 class 不会。您可以手动为它们编写适当的 equalshashcode 实现(IntelliJ IDEA 可以为您生成),或者您可以将它们更改为数据 classes.

此外,在大多数情况下,密封接口比密封 classes 使用起来更干净一些。 Kotlin 中有这么多密封 classes 示例的原因可能是直到最近(Kotlin 1.5)才支持密封接口。

这里是定义项目的方法 classes:

sealed interface RoutineItem {
    val id: String

    data class Header(
        override val id: String = UUID.randomUUID().toString(),
        val workout: String,
        val unit: String,
    ) : RoutineItem

    data class Detail(
        override val id: String = UUID.randomUUID().toString(),
        val set: Int,
        var weight: String = "",
        var reps: String = "",
    ) : RoutineItem
}

除此之外,您分享的 DetailAdapter 代码看起来很不完整。它没有实际尝试将任何数据绑定到视图。

另一个小提示:由于 DiffUtil.ItemCallbacks 通常不携带任何状态,您可以将它们定义为 object 而不是 class,这样您就不必调用它们构造函数或有它们的多个实例。