Hi everyone, I’m getting `IllegalStateException F...
# coroutines
a
Hi everyone, I’m getting
IllegalStateException Flow invariant is violated emission from another coroutine is detected
when running this code, is it possible to fix this without using channelFlow ?
Copy code
flow<Action> {
    val result = downloadFile(url, directory) { event: ProgressEvent ->
        emit(DownloadProgress(event))
    }
    emit(DownloadFinished("path"))
}.onEach { L.d(it) }.launchIn(viewLifecycleOwner.lifecycleScope)
downloadFile method
Copy code
suspend fun downloadFile(
    url: String, fileDir: String, onProgressEvent: suspend (event: ProgressEvent) -> Unit = {}) {
 val progressChannel = Channel<ProgressEvent>()

 CoroutineScope(coroutineContext).launch {
     progressChannel.consumeAsFlow().collect { onProgressEvent.invoke(it) }
  }
/* rest of the code */
}
z
I don't think so, unless you refactor
downloadFile
to not invoke the callback from a new coroutine. Since presumably "rest of code" is sending something into the channel, why not just invoke the callback directly?
Also
channel.consumeAsFlow().collect{}
is probably redundant, just do
channel.consumeEach{}
or use a for loop.
a
thanks for advice 👍 I’ll use for loop
let me explain more about
Channel
in downloadfile method, channel used as an event bus which is passed in okhttp interceptor and when there is a file downloading, it will post values so I can’t invoke callback directly I must listen to channel changes
Seems like this solution is working
Copy code
flow<Action> {
    val flowContext = coroutineContext
    val result = downloadFile(url, directory) { event: ProgressEvent ->
        withContext(flowContext){
        emit(DownloadProgress(event))
       }
    }
    emit(DownloadFinished("path"))
}.onEach { L.d(it) }.launchIn(viewLifecycleOwner.lifecycleScope)
I’m using flow context and then emitting value
285 Views