首页 > 解决方案 > 如何根据 LiveData Map 过滤 LiveData List?

问题描述

我要异步操作。在 viewmodel 中,两者需要一起为 UI 工作。如何根据 de LiveData 地图中的键过滤 LiveData 列表?(列表中的对象 id 对应于 Map 键)

@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
private val _allJourneys = MutableLiveData<List<Journey>>()
val allJourneys: LiveData<List<Journey>> get() = _allJourneys

@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
private val _enrolledMap = MutableLiveData<Map<String, String>>()
val enrolledMap: LiveData<Map<String, String>> get() = _enrolledMap

fun getEnrolled() {
    viewModelScope.launch {
        progressRepository.getEnrolledJourneysMapOfUser().observeForever {
            Timber.d("Map values: $it")
            _enrolledMap.value = it
        }
    }

}

fun getJourneys() {
    viewModelScope.launch {
        journeysRepository.getAll().observeForever { it ->
            _allJourneys.value = it.filter {
               // enrolledMap.containsKey(it.id) ??? Nullpointer
            }
        }
    }
}

标签: kotlinandroid-livedatamutablelivedata

解决方案


observeForever在 ViewModel 中是错误的方法。每次get__调用时,都会进行一个新的订阅,并且您将获得多个订阅,并且可能会在 ViewModel 中出现内存泄漏,直到垃圾收集器清除卡住的订阅。

相反,当您使用 LiveData 时,您应该只使用返回值并将它们保留为字段。

val allJourneys: LiveData<List<Journey>> get() = journeysRepository.getAll()
    
val enrolledMap: LiveData<Map<String, String>> get() = progressRepository.getEnrolledJourneysMapOfUser()

//fun getEnrolled() {
//    viewModelScope.launch {
//        .observeForever {
//            Timber.d("Map values: $it")
//            _enrolledMap.value = it
//        }
//    }
//
//}

//fun getJourneys() {
//    viewModelScope.launch {
//        .observeForever { it ->
//            _allJourneys.value = it.filter {
//               // enrolledMap.containsKey(it.id) ??? Nullpointer
//            }
//        }
//    }
//}

因为来自 DAO 的存储库中的 LiveData 已经处理后台数据获取。

如果这是通过存储库中的挂起函数手动完成的,那么您可以使用switchMap+ liveData { emitSource- 但在这种情况下,似乎没有必要。


推荐阅读