android - 后台线程上的 Android 实时数据转换
问题描述
我看到了这个,但我不确定如何实现它,或者如果这是同一个问题,我有一个调解器实时数据,当它的 2 个源实时数据更新或基础数据(房间数据库)更新时,它会更新似乎工作正常,但如果数据更新很多,它会快速连续刷新很多,我得到一个错误
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
这不会每次都发生,只有当数据库快速连续更新大量更新时,才会出现视图模型的问题部分,
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 返回 Pager 来强制调用关闭主线程,它确实可以工作并且我不再收到错误但它显然会阻塞ui,那么有没有办法使 switchmap 异步或使 searchAndFilterPokemonPager 方法异步返回寻呼机?我知道第二个在技术上是可行的(从异步返回),但也许协程有办法解决这个问题,
感谢您的帮助
解决方案
根据@EpicPandaForce 的建议,我有这个解决方案
val combinedValues =
MediatorLiveData<Pair<String?, MutableSet<String>?>?>().apply {
addSource(search) {
value = Pair(it, filters.value)
}
addSource(filters) {
value = Pair(search.value, it)
}
}
searchPokemon = combinedValues.switchMap {
liveData {
val search = it?.first ?: return@liveData
val filters = it.second ?: return@liveData
withContext(Dispatchers.IO){
emitSource(searchAndFilterPokemonPager(search, filters.toList()))
}
}.distinctUntilChanged()
}
但我仍然收到此错误
E/ROOM: Cannot run invalidation tracker. Is the db closed?
java.lang.IllegalStateException: Cannot access database on the main thread since it may potentially lock the UI for a long period of time.
在块中的行 searchPokemonForPaging(search) 上抛出
@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 searchPokemonForPaging(search: String): PagingSource<Int, PokemonWithTypesAndSpeciesForList> {
return repository.searchPokemonWithTypesAndSpeciesForPaging(search)
}
回购方法
fun searchPokemonWithTypesAndSpeciesForPaging(search: String): PagingSource<Int, PokemonWithTypesAndSpeciesForList> {
return pokemonDao.searchPokemonWithTypesAndSpeciesForPaging(search)
}
道法
@Transaction
@Query("SELECT pokemon_id, pokemon_name, pokemon_image_url, pokemon_sprite FROM Pokemon WHERE pokemon_name LIKE :search ORDER BY pokemon_id ASC")
fun searchPokemonWithTypesAndSpeciesForPaging(search: String): PagingSource<Int, PokemonWithTypesAndSpeciesForList>
推荐阅读
- c - 用于浮点返回非预期值的 abs 函数 C
- github - Amazon Sagemaker 失败:请检查您是否有与 git 存储库同名的目录?
- apache-spark - 带有多个 .jar 的 SparkSubmitOperator
- mysql - TypeORM 不是唯一的表/别名:'TABLE_NAME'
- ipfs - js-ipfs将文件添加到节点无法正常工作
- python - 使用 -beautiful-soup 在 python 中的表列中获取 href 链接
- javascript - Javascript函数不适用于多个循环进度条
- php - 具有多个按钮的 PHP 操作重置其他按钮
- node.js - Javascript API 进度反馈给前端
- calendar - 我们如何在 Apache Superset 中使用 Jalali 日历?