android - 违反流异常透明度 : Emission from another coroutine is detected

标签 android kotlin-coroutines android-jetpack

我正在尝试在我的项目中实现 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()
    }
我的 View 模型类:
    init {
        viewModelScope.launch {
            repository.getCategories().collectLatest {
                if(it.data!=null){
                    _categories.value = it.data
                    Log.d("appDebug", " ViewModel : $it")
                }
            }
        }
    }

最佳答案

正如异常(exception)所说,冷流不允许 emit()同时。
你有两个选择:

  • 替换 flow { }channelFlow { }并使用 send() 发送值(在你的情况下可能更容易)
  • 确保没有 emit()被同时调用
  • 关于android - 违反流异常透明度 : Emission from another coroutine is detected,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67582210/

    相关文章:

    java - 使用按钮更改 fragment 的大小

    android - 如何在android java中获取 bool 数组的值?

    android - 如何重新启动 livedata builder 功能?

    android - 我怎么知道特定协程调度程序使用的线程数是多少?

    android - jetpack compose 中文本颜色的奇怪行为

    android - android 中的离线 map (.obf 文件)?

    java - 不幸的是(android应用程序)已经停止了。空指针异常

    android - Kotlin 流 : How can i get the cache data from subscription in flow when i have new subscriber?

    android - Jetpack 组合单个数字文本字段

    java - 为特定应用程序模块启用 Android X