我看到了this但我不确定如何实现它,或者如果这是同一个问题,我有一个调解器实时数据,当其 2 个源实时数据更新或底层数据(Room db)更新时,它会更新,它似乎可以工作很好,但是如果数据更新很多,它会快速连续刷新很多,并且我会收到错误
Cannot run invalidation tracker. Is the db closed?
Cannot access database on the main thread since it may potentially lock the UI for a long period of time
这种情况不会每次都会发生,只有当数据库连续快速更新时才会发生,这就是 View 模型的问题部分,
var search: MutableLiveData<String> = getSearchState()
val filters: MutableLiveData<MutableSet<String>> = getCurrentFiltersState()
val searchPokemon: LiveData<PagingData<PokemonWithTypesAndSpeciesForList>>
val isFiltersLayoutExpanded: MutableLiveData<Boolean> = getFiltersLayoutExpanded()
init {
val combinedValues =
MediatorLiveData<Pair<String?, MutableSet<String>?>?>().apply {
addSource(search) {
value = Pair(it, filters.value)
}
addSource(filters) {
value = Pair(search.value, it)
}
}
searchPokemon = Transformations.switchMap(combinedValues) { pair ->
val search = pair?.first
val filters = pair?.second
if (search != null && filters != null) {
searchAndFilterPokemonPager(search, filters.toList())
} else null
}.distinctUntilChanged()
}
@SuppressLint("DefaultLocale")
private fun searchAndFilterPokemonPager(search: String, filters: List<String>): LiveData<PagingData<PokemonWithTypesAndSpeciesForList>> {
return Pager(
config = PagingConfig(
pageSize = 20,
enablePlaceholders = false,
maxSize = 60
)
) {
if (filters.isEmpty()){
searchPokemonForPaging(search)
} else {
searchAndFilterPokemonForPaging(search, filters)
}
}.liveData.cachedIn(viewModelScope)
}
@SuppressLint("DefaultLocale")
private fun getAllPokemonForPaging(): PagingSource<Int, PokemonWithTypesAndSpecies> {
return repository.getAllPokemonWithTypesAndSpeciesForPaging()
}
@SuppressLint("DefaultLocale")
private fun searchPokemonForPaging(search: String): PagingSource<Int, PokemonWithTypesAndSpeciesForList> {
return repository.searchPokemonWithTypesAndSpeciesForPaging(search)
}
@SuppressLint("DefaultLocale")
private fun searchAndFilterPokemonForPaging(search: String, filters: List<String>): PagingSource<Int, PokemonWithTypesAndSpeciesForList> {
return repository.searchAndFilterPokemonWithTypesAndSpeciesForPaging(search, filters)
}
该错误实际上是由函数 searchPokemonForPaging 引发的
例如,当应用程序启动时会发生这种情况,该应用程序会执行大约 300 次写入,但如果我通过暂停所有内容并使用 runBlocking 返回寻呼机来强制调用关闭主线程,它确实可以工作,并且我不再收到错误,但是它显然会阻塞用户界面,那么有没有办法使 switchmap 异步或使 searchAndFilterPokemonPager 方法异步返回寻呼机?我知道第二个在技术上是可能的(从异步返回),但也许协程有办法解决这个问题
感谢您的帮助
最佳答案
您可以使用 combineTuple (which is available as a library that I wrote for this specific purpose) 简化组合(可选)
之后,您可以使用 liveData {
协程构建器将执行移至后台线程
现在您的代码将如下所示
val search: MutableLiveData<String> = getSearchState()
val filters: MutableLiveData<Set<String>> = getCurrentFiltersState()
val searchPokemon: LiveData<PagingData<PokemonWithTypesAndSpeciesForList>>
val isFiltersLayoutExpanded: MutableLiveData<Boolean> = getFiltersLayoutExpanded()
init {
searchPokemon = combineTuple(search, filters).switchMap { (search, filters) ->
liveData {
val search = search ?: return@liveData
val filters = filters ?: return@liveData
withContext(Dispatchers.IO) {
emit(searchAndFilterPokemonPager(search, filters.toList()))
}
}
}.distinctUntilChanged()
}
关于Android 后台线程上的实时数据转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65539628/