RecyclerView 存在 Room 数据库问题 - Room 数据库已更新,但 recyvlerView 未正确显示所有项目

问题描述 投票:0回答:2

我已经使用 room db liveData 设置了 recyclerView。我正在更新 db 和 recyvlerView 项目更改,但不一致。当我重新创建 recyclerView 或重新启动应用程序时,它会正确显示所有更新的数据。 我几个月来一直面临这个问题,但找不到原因。

这是 Db 的项目:

@Entity(tableName = "items_table")
data class MyItem(
    var title: String = "null",
) {
    @PrimaryKey(autoGenerate = true)
    var id: Long = 0L
}

观察到的 liveData 查询:

@Query("SELECT * FROM items_table ORDER BY id DESC")
fun getAllItemsSortedByDate(): LiveData<List<MyItem>>

...
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertMyItem(myItem: MyItem)

MainActivity代码部分观察并更新recyclerView:

 ...

    setupRecyclerView()

    mainMyItemsViewModel.allItemsSortedByDate.observe(this) {
        myItemsAdapter.submitList(it)

        //issue is: nothing updates correctly on recyclerView unless view recreated.

        // myItemsAdapter.notifyItemChanged(0)
        myItemsAdapter.notifyDataSetChanged()

    }
   
  //insert on a floatingActionButton click. Then observe data change.
 binding.floatingActionButtonPool.setOnClickListener {
            CoroutineScope(Dispatchers.IO).launch {
                mainMyItemsViewModel.id++
                mainMyItemsViewModel.insertMyItem(MyItem("Hello World. ${mainMyItemsViewModel.id}"))
            }
        }
 ...

 private fun setupRecyclerView() = binding.recyclerViewPool.apply {
    myItemsAdapter = MyItemsAdapter()

    adapter = myItemsAdapter
    if (layoutManager == null)
        layoutManager = LinearLayoutManager(context, RecyclerView.VERTICAL, false)


}

整个适配器:

class MyItemsAdapter :
RecyclerView.Adapter<MyItemsAdapter.ViewHolder>() {
private var _binding: ItemsListPresenterBinding? = null // this just one textView in constraint layout
private val binding get() = _binding!!

private var selectedPosition: Int = 0
private var dataSet: List<MyItem> = mutableListOf()


/**
 * Provide a reference to the type of views that you are using
 * (custom ViewHolder).
 */
class ViewHolder(view: View) : RecyclerView.ViewHolder(view)

// Create new views (invoked by the layout manager)
override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): ViewHolder {
    _binding = ItemsListPresenterBinding.inflate(
        LayoutInflater.from(viewGroup.context),
        viewGroup, false
    )

    return ViewHolder(
        binding.root
    )
}


fun submitList(list: List<MyItem>) = run {

    dataSet = list

    //Log.d("Tag", " dataset size : " + dataSet.size.toString())


}

override fun onBindViewHolder(holder: ViewHolder, position: Int) {

     // I suspect this adapter is the issue.

    //holder.itemView.setBackgroundColor(if (selectedPosition == position) Color.GREEN else Color.DKGRAY)

    val item = dataSet[position] // also tested with adapterPosition...

    binding.textViewItem.text = item.title + "\nID: " + item.id


}


// Return the size of your dataset (invoked by the layout manager)
override fun getItemCount() = dataSet.size

}

问题是,当我插入新项目或更新项目时,它不会显示新项目,而是不断填充重复的上一个项目。

如果需要,我将上传整个测试项目。

如果这足以检查原因,并且有人知道解决方案,请告诉我解决方案。

显示重复问题的应用程序图像:

android android-recyclerview android-room
2个回答
1
投票

在 MainActivity 中更新观察者回调

mainMyItemsViewModel.allItemsSortedByDate.observe(this) {
        myItemsAdapter.submitList(it)
}

更新适配器中的submitList方法

fun submitList(list: List<MyItem>) = run {

    dataSet.clear()
    dataSet.addAll(list)
    notifyDataSetChanged()
    //Log.d("Tag", " dataset size : " + dataSet.size.toString()
}

适配器:

class MyItemsAdapter :
    RecyclerView.Adapter<MyItemsAdapter.ViewHolder>() {
    private var selectedPosition: Int = 0
    private var dataSet: List<MyItem> = mutableListOf()

    /**
     * Provide a reference to the type of views that you are using
     * (custom ViewHolder).
     */
    class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
        var binding = ItemsListPresenterBinding.bind(view)
    }

    // Create new views (invoked by the layout manager)
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        return ViewHolder(
            LayoutInflater.from(parent.context).inflate(R.layout.item_list_presenter, parent, false)
        )
    }

    fun submitList(list: List<MyItem>) {
        dataSet.clear()
        dataSet.addAll(list)
        notifyDataSetChanged()
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        // I suspect this adapter is the issue.
        //holder.itemView.setBackgroundColor(if (selectedPosition == position) Color.GREEN else Color.DKGRAY)
        val item = dataSet[position] // also tested with adapterPosition...
        holder.binding.textViewItem.text = item.title + "\nID: " + item.id
    }


    // Return the size of your dataset (invoked by the layout manager)
    override fun getItemCount() = dataSet.size

}

0
投票

我的应用程序也有同样的问题。如果我错了请告诉我,但由于

RecyclerView
之后有一个按钮,我猜您在
RecyclerView
中使用了
ScrollView
。对吗?

就我而言,我有这种奇怪的行为,我可以将项目添加到数据库,观察者被触发,但

RecyclerView
没有显示新项目。

我在此线程上找到了解决方案:ScrollView 中的 RecyclerView 不起作用

如果您使用的是

ScrollView
,请将其替换为
NestedScrollView 

© www.soinside.com 2019 - 2024. All rights reserved.