android - 违反流异常透明度:检测到来自另一个协程的发射
问题描述
我正在尝试在我的项目中实现 NetworkBoundResource 类,这就是我正在尝试的。一切正常,得到响应,缓存但是当我在 flowBuilder 中发出值时,它会崩溃并显示这个错误。
我得到的错误:
Emission from another coroutine is detected.
Child of ProducerCoroutine{Active}@df26eb9, expected child of FlowCoroutine{Active}@a0bb2fe.
FlowCollector is not thread-safe and concurrent emissions are prohibited.
To mitigate this restriction please use 'channelFlow' builder instead of 'flow')' has been detected.
Emissions from 'catch' blocks are prohibited in order to avoid unspecified behaviour, 'Flow.catch' operator can be used instead.
For a more detailed explanation, please refer to Flow documentation.
NetworkBoundResource 类:
abstract class NetworkBoundResource<ResultType, RequestType> {
fun invoke(): Flow<Resource<ResultType>> = flow {
val rawData = loadFromDb()
if (shouldFetch(rawData)) {
fetchDataFromServer()
.onStart { emit(Resource.loading(rawData)) } // emit() causing issue
.catch { emit(Resource.error(it, null)) } // emit() causing issue
.collectLatest { }
}
}
// Save API response result into the database
protected abstract suspend fun cacheInDb(items: RequestType)
// Need to fetch data from server or not.
protected abstract fun shouldFetch(data: ResultType?): Boolean
// Show cached data from the database.
protected abstract suspend fun loadFromDb(): ResultType
// Fetch the data from server.
protected abstract suspend fun fetchDataFromServer(): Flow<ApiResponse<List<Category>>>
// when the fetch fails.
protected open fun onFetchFailed() {}
}
存储库类:
fun getCategories(): Flow<Resource<List<Category>>> {
return object : NetworkBoundResource<List<Category>, List<Category>>() {
override suspend fun cacheInDb(items: List<Category>) {
withContext(Dispatchers.IO) { database.getCategories().insert(items) }
}
override fun shouldFetch(data: List<Category>?): Boolean {
return true
}
override suspend fun loadFromDb(): List<Category> {
return withContext(Dispatchers.IO) { database.getCategories().read() }
}
override suspend fun fetchDataFromServer(): Flow<ApiResponse<List<Category>>> {
return flow { emit(RetrofitModule.getCategories()) }
}
}.invoke()
}
我的视图模型类:
init {
viewModelScope.launch {
repository.getCategories().collectLatest {
if(it.data!=null){
_categories.value = it.data
Log.d("appDebug", " ViewModel : $it")
}
}
}
}
解决方案
正如例外所说,冷流不允许emit()
同时进行。你有两个选择:
- 替换
flow { }
为channelFlow { }
并发送值send()
(在您的情况下可能更容易) - 确保
emit()
同时调用no
推荐阅读
- javascript - Alexa ask-cli 如何添加自定义 https 服务器
- matlab - Gurobi 的 Runtime 属性是否包含接口的时间
- typescript - TypeScript - 将返回类型定义为输入类型
- javascript - Need to hide row of ngx-datatable based on row index
- angular - Directive use a class selector
- javascript - 包含按钮的书签
- node.js - 错误的文件描述符,读取,同时使用 node-stream-zip 提取 zip 文件
- vb.net - 在 TextBox Visual Basic 中显示来自 DataGridView 的数据
- kendo-ui - 如何使用 jquery 刷新剑道上传器小部件
- mysql - 如何使用 Codeigniter 在 Excel 中并排插入 mysql 数据或值?