拖放后如何正确更新回收器视图的适配器列表?



我有一个RecyclerView,其中包含从Room数据库中提取的项目。项目的移动是通过ItemTouchHelper实现的。每个项目都有一个位置属性,该属性在移动项目时会正确更改。移动项目后,会向数据库发送更新,但这不会在RecyclerView中显示。

视图模型:

val items: LiveData<List<Item>> = database.getItemsByPosition()
fun movePositions(fromPosition: Int, toPosition: Int) {

// code to update positions here
uiScope.launch {
withContext(Dispatchers.IO) {
databaseDao.updateItems(items.value!!)
}
}
}

数据库道:

@Query("SELECT * FROM item_table ORDER BY position")
fun getItemsByPosition(): LiveData<List<Item>>

在onCreateView:上的片段中

viewModel.items.observe(viewLifecycleOwner, {
it?.let {
for (item in it) {
Log.d("Observer", "Item ${item.id}, position ${item.position}")
}
adapter.submitList(it)
}
})

Fragment有一个项目的观察者。通过使用Log.d,我验证了项目是否正确更新,但在提交时没有任何更改。由于submitList倾向于忽略对同一列表的更改,所以我也尝试了adapter.submitList(ArrayList(it)),但没有成功。

当我把项目1(位置A(移到位置B时,项目2(原来在位置B上(似乎移到了位置A,而项目1只向上或向下移动了一个。这与日志不一致,当重新加载视图时,顺序是应该的。为什么它不能通过拖放正确更新?

为了更清楚,这里有一个简短的演示

你尝试过类似RecyclerView.NotifyDataSetChanged的东西吗?

直接从Room数据库使用LiveData似乎会导致意外行为,因此我尝试不直接从数据库使用LiveData来解决问题。

现在取代

val items: LiveData<List<Item>> = databaseDao.getItemsByPosition()

我使用

private val _items = MutableLiveData<List<Item>>()
val items: LiveData<List<Item>>
get() = _item
init {
uiScope.launch {
withContext(Dispatchers.IO) {
_items.postValue(databaseDao.getItemsByPosition())
}
}
}
fun movePositions(fromPosition: Int, toPosition: Int) {
// code to update positions here
uiScope.launch {
withContext(Dispatchers.IO) {
databaseDao.updateItems(items.value!!)
}
}
}

这解决了项目的移动问题。这意味着这些项目不再总是与文件室数据库同步。例如,在RecyclerView中没有显示向数据库添加新项目。我通过在数据库插入后添加以下行解决了这个问题。

_items.postValue(databaseDao.getItemsByPosition())

虽然这并不能解释我最初遇到的问题,但这是一个变通方法,希望对其他人有用。

最新更新