【发布时间】:2021-03-12 21:35:07
【问题描述】:
我一直在试图弄清楚如何更新我的 RecyclerView 显示的列表。
我要做的是在更改微调器时显示显示列表的子集。我的数据库中有一组动物,其中一些将其pet 属性设置为true,而另一些将其设置为false。
将 Room Database 与存储库和 viewModel 一起使用,而我一直在努力拼凑的是,拥有三个不同的列表是很好的,我可以调整到,所以在 m
存储库:
class AnimalRepository(private val animalDao: AnimalDao) {
val allAnimals: Flow<List<Animal>> = animalDao.getAnimalsByCategory()
val pets: Flow<List<Animal>> = animalDao.getAnimalsByPetStatus(true)
val nonPets: Flow<List<Animal>> = animalDao.getAnimalsByPetStatus(false)
@Suppress("RedundantSuspendModifier")
@WorkerThread
suspend fun insert(animal: Animal) {
animalDao.insert(animal)
}
@WorkerThread
suspend fun get(id: Int): Animal {
return animalDao.get(id)
}
@WorkerThread
suspend fun delete(id: Int) {
animalDao.delete(id)
}
}
视图模型
class AnimalViewModel(private val repository: AnimalRepository) : ViewModel() {
var allAnimals: LiveData<List<Animal>> = repository.allAnimals.asLiveData()
val pets: LiveData<List<Animal>> = repository.pets.asLiveData()
val nonPets: LiveData<List<Animal>> = repository.nonPets.asLiveData()
var result: MutableLiveData<Animal> = MutableLiveData<Animal>()
var mode: VIEW_MODES = VIEW_MODES.BOTH
/*
* Launching a new coroutine to insert the data in a non-blocking way
* */
fun insert(animal: Animal) = viewModelScope.launch {
repository.insert(animal)
}
/*
* Launching a new coroutine to get the data in a non-blocking way
* */
fun get(id: Int) = viewModelScope.launch {
result.value = repository.get(id)
}
fun delete(id: Int) = viewModelScope.launch {
repository.delete(id)
}
}
class AnimalViewModelFactory(private val repository: AnimalRepository) : ViewModelProvider.Factory {
override fun <T: ViewModel> create(modelClass: Class<T>): T {
if (modelClass.isAssignableFrom(AnimalViewModel::class.java)) {
@Suppress("UNCHECKED_CAST")
return AnimalViewModel(repository) as T
}
throw IllegalArgumentException("Unknown ViewModel class")
}
}
在我的MainActivity 中,我在这三个列表中设置了一个观察者,并且根据哪个视图模式处于活动状态(微调器设置视图模式),该列表被输入到我的 RecyclerView 的 ListAdapter 的 submitList
animalViewModel.allAnimals.observe(this) { animals ->
if (viewMode == VIEW_MODES.BOTH) {
animals.let {
adapter.submitList(it)
// recyclerView.adapter = adapter
}
}
}
animalViewModel.pets.observe(this) { animals ->
if (viewMode == VIEW_MODES.PETS) {
animals.let {
adapter.submitList(it)
// recyclerView.adapter = adapter
}
}
}
animalViewModel.nonPets.observe(this) { animals ->
if (viewMode == VIEW_MODES.NON_PETS) {
animals.let {
adapter.submitList(it)
}
}
}
我正在用我的微调器改变模式
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
when (position) {
0 -> {
viewMode = VIEW_MODES.BOTH
}
1 -> {
viewMode = VIEW_MODES.PETS
}
2 -> {
viewMode = VIEW_MODES.NON_PETS
}
}
adapter.notifyDataSetChanged()
}
如果在更改视图模式后添加或删除动物,这很好用,因为观察者触发并且允许正确的动物填充适配器,但 notifyDataSetChanged() 没有做任何事情,我一直坚持无需在列表中添加或删除即可更新的适配器
我也尝试在观察者中重置适配器,但也没有做任何事情
我对 kotlin 和 android 编程非常陌生,我确定我的做法是错误的,但有没有办法强制刷新列表?
更新:
我想我可能已经找到了一个解决方案,但我担心它很老套。在我的 ViewModel 中,我将 allAnimals 的内容替换为过滤后的列表
fun showBoth() {
allAnimals = repository.allAnimals.asLiveData()
}
fun showPets() {
allAnimals = repository.pets.asLiveData()
}
fun showNonPets() {
allAnimals = repository.nonPets.asLiveData()
}
然后在我的主要活动中,我在处理微调器更改时更改了我的逻辑,以告诉视图模型做它的事情,然后移除观察者并将其重新打开
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
when (position) {
0 -> {
animalViewModel.showBoth()
}
1 -> {
animalViewModel.showPets()
}
2 -> {
animalViewModel.showNonPets()
}
}
refreshObserver()
}
private fun refreshObserver() {
animalViewModel.allAnimals.removeObservers(this)
animalViewModel.allAnimals.observe(this) { animals ->
animals.let {
adapter.submitList(it)
}
}
}
这似乎可以让回收站视图更新,但它是 hacky 吗?
【问题讨论】:
标签: android kotlin android-recyclerview android-room android-livedata