【问题标题】:Switch from Main dispatcher to IO dispatcher from non lifecycle class从非生命周期类从主调度器切换到 IO 调度器
【发布时间】:2022-02-05 21:08:05
【问题描述】:

我在我的 android 应用程序中使用协程,我有这个需要与 UI 和主线程通信的功能。

private suspend fun init() : RequestProcessor<LocalData, ApiResult, ApiError>
{
    @Suppress("LeakingThis")
    _localData = listener.databaseCall()
    
    withContext(Dispatchers.IO) {
        
        if (_localData == null)
        {
            checkIfShouldFetch(null, null)
        }
        else
        {
            withContext(Dispatchers.Main) {
                
                mediatorLiveData.addSource(_localData!!) { newLocalData ->
                    mediatorLiveData.removeSource(_localData!!)
                    
                    // I want to call this from the IO thread.
                    checkIfShouldFetch(newLocalData, _localData)
                }
            }
        }
    }
    
    return this
}

我的问题是,如何从嵌套上下文(Main)回到根上下文(IO)?

当我再次调用 withContext(Dispatchers.IO) 时显示此错误:只能在协程主体内调用暂停函数

我需要从 IO 上下文中调用函数 checkIfShouldFetch(newLocalData, _localData),但我没有找到方法。

【问题讨论】:

  • 您的问题不是嵌套withContext,而是试图从常规的非挂起回调的主体中调用挂起函数。以下答案之一涵盖了如何将带有回调的异步调用转换为可暂停的同步调用。

标签: android kotlin kotlin-coroutines coroutine


【解决方案1】:

你需要启动一个协程在那个地方调用withContext。在不启动协程的情况下,您可以尝试使用suspendCoroutinesuspendCancellableCoroutine 来暂停执行,直到触发回调:

withContext(Dispatchers.Main) {
    val newLocalData = addSource()
    checkIfShouldFetch(newLocalData, _localData)
}

suspend fun addSource(): LiveData<...> = suspendCoroutine { continuation ->
    mediatorLiveData.addSource(_localData) { newLocalData ->
        mediatorLiveData.removeSource(_localData)

        continuation.resumeWith(newLocalData)
    }
}

suspend fun checkIfShouldFetch(newLocalData: ..., _localData: ...) = withContext(Dispatchers.IO) {
    // ...
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-22
    • 1970-01-01
    • 2015-05-09
    • 1970-01-01
    • 1970-01-01
    • 2021-12-15
    相关资源
    最近更新 更多