【发布时间】:2020-11-02 01:59:45
【问题描述】:
我正在为 Android 编写一个简单的待办事项列表样式应用程序,但在添加排序功能时遇到了问题。
我有一个带有RecyclerView 的屏幕,显示属于该用户的所有列表,我想添加一个允许用户打开或关闭排序的功能。问题是我似乎无法找到一种方法让向用户显示的列表在进行另一次更改后保持一致的排序。
假设列表保存在Room 数据库中。
实现我想要的最简单和最一致的方法是对数据库本身的数据进行排序,但这可能不是要走的路,因为实现起来会很复杂(如果可能的话)。
我很可能应该在我的视图模型中对数据进行本地排序。我想我可以使用MediatorLiveData 来做到这一点,它会观察数据库,而主机活动本身会观察到它。在更新 MediatorLiveData 之前,我会使用标志 isSorting 对列表进行排序,以便按原样返回数据或在传递结果之前对其进行排序。
我的问题的关键是我希望能够打开和关闭此功能,同时仍保持之后的数据顺序(执行另一个操作时)。以下是典型事件流的示例:
- 用户打开应用,数据库返回:“list 3”、“list 1”、“list 2”。
- 数据按原样(未排序)显示给用户
- 用户开启排序功能
- 视图模型在本地对后备列表进行排序
- 活动中的观察者收到排序列表
- 活动现在显示“列表 1”、“列表 2”、“列表 3”
- 用户添加了一个新列表:“list 4”。
在我进入问题部分之前,这里有一些代码:
存储库(为简洁而缩写):
class ListsRepository {
val db = Database().getInstance();
fun getAllUserLists(userId: Int): LiveData<List<UserList>>
}
活动(为简洁起见):
class UserListsActivity: Activity() {
val viewModel: UserListsViewModel
val adapter: UserListAdapter
fun onCreate(savedInstanceState: Bundle?) {
viewModel.allLists.observe(this, Observer { newData ->
adapter.setData(newData)
adapter.notifyDataSetChanged()
)
}
}
Viewmodel(为简洁起见)
class UserListsViewModel(val userId: Int, val repository: ListsRepository ): ViewModel() {
val allLists = MediatorLiveData<List<UserList>>()
val isSorting = false
init {
allLists.addSource(repository.getAllUserLists(userId)) { userLists ->
val result = userLists
if(isSorting) {
result = result.sortedBy { it.name }
}
value = result
}
}
}
现在让我们进入实际问题:
只要打开排序功能,一切正常,用户将看到“列表 1”、“列表 2”、“列表 3”、“列表 4”。
但是现在,假设用户关闭了排序功能,并添加了另一个列表“列表 0”
现在发生的是:
-
MediatorLiveData从数据库接收更新为“列表 3”、“列表 1”、“列表 2”、“列表 4”、“列表 0”(数据库的原始顺序,加上新列表) -
isSorting标志已关闭,因此它按原样将值设置为返回的数据 - 向用户显示的数据未排序,但之前的排序现在丢失了
期望的结果:"list 1","list 2","list 3","list 4","list 0"(未排序,但保留之前的顺序)
实际结果:"list 3","list 1","list 2","list 4","list 0"(之前对列表 1,2,3 的排序现在丢失了)。
我希望我说清楚了。这是否可以在不增加太多复杂性的情况下实现?在 Android 应用中提供排序功能的“标准方式”是什么?
谢谢
【问题讨论】:
-
你是说数据库响应的顺序是实现我想要的关键吗?因为我只以
Room为例,但这个问题的含义更广泛。而且,除了插入之外,还有其他操作,比如重命名。 -
这里有一条评论建议我应该始终排序,但只在 DB 的大小减去 1 之前。该评论现在被删除,但我想发表评论以防其他人想到这一点。这种方法可能适用于添加项目,但不适用于删除。想象一下 DB 持有 3,4,1,2。用户打开排序并获得 1,2,3,4。现在用户关闭排序并删除列表 4。数据库现在保存 3,1,2,如果视图模型只排序到最后一个条目,用户将获得 1,3,2 我希望他看到的位置1,2,3
标签: android sorting mvvm viewmodel repository-pattern