我已经使用 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
}
问题是,当我插入新项目或更新项目时,它不会显示新项目,而是不断填充重复的上一个项目。
如果需要,我将上传整个测试项目。
如果这足以检查原因,并且有人知道解决方案,请告诉我解决方案。
显示重复问题的应用程序图像:
在 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
}
我的应用程序也有同样的问题。如果我错了请告诉我,但由于
RecyclerView
之后有一个按钮,我猜您在 RecyclerView
中使用了 ScrollView
。对吗?
就我而言,我有这种奇怪的行为,我可以将项目添加到数据库,观察者被触发,但
RecyclerView
没有显示新项目。
我在此线程上找到了解决方案:ScrollView 中的 RecyclerView 不起作用
如果您使用的是
ScrollView
,请将其替换为 NestedScrollView
。