Switch from Main dispatcher to IO dispatcher from non lifecycle class

Viewed 582

I m using coroutines in my android app, and i have this function that need to communicate with UI and Main thread.

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
}

My question is, how to come back to the root context (IO) from the nested context (Main)?

when i call again withContext(Dispatchers.IO) this error is displayed : Suspension functions can be called only within coroutine body

I need to call the function checkIfShouldFetch(newLocalData, _localData) from the IO context and i didn't find how to do it.

1 Answers

You would need to launch a coroutine to call withContext in that place. What you can try to do without launching a coroutine is to use suspendCoroutine or suspendCancellableCoroutine to suspend execution until callback is fired:

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) {
    // ...
}
Related