Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Flow.collect still receive value after invoke CoroutineContext.cancel #1753

Closed
baoti opened this issue Jan 7, 2020 · 2 comments
Closed

Flow.collect still receive value after invoke CoroutineContext.cancel #1753

baoti opened this issue Jan 7, 2020 · 2 comments
Labels

Comments

@baoti
Copy link

baoti commented Jan 7, 2020

viewLifecycleOwner.lifecycleScope.launchWhenCreated {
    flow {
        while (true) {
            delay(Random.nextLong(50) + 10)
            emit("launchWhenCreated - ${SystemClock.uptimeMillis()}")
        }
    }
        .flowOn(Dispatchers.Default)
        .collect {
            val currentState = viewLifecycleOwnerLiveData.value?.lifecycle?.currentState
            Timber.d("collect: $value - $currentState")
            if (currentState.isAtLeast(Lifecycle.State.CREATED) != true) {
                // this.isActive == false
                Timber.w("Oops! collect: $value - $currentState")
            }
        }
}

In LifecycleCoroutineScopeImpl.onStateChanged(ON_DESTROY), called coroutineContext.cancel(), but collect still receive value on next loop.

@ThanosFisherman
Copy link

ThanosFisherman commented Jan 10, 2020

I encountered the same problem here

https://stackoverflow.com/questions/59680533/how-to-cancel-unsubscribe-from-coroutines-flow

A workaround is mentioned in #1265

I have replaced every single collect with a safeCollect function in my project:

/**
 * Only proceed with the given action if the coroutine has not been cancelled.
 * Necessary because Flow.collect receives items even after coroutine was cancelled
 * https://github.com/Kotlin/kotlinx.coroutines/issues/1265
 */
suspend inline fun <T> Flow<T>.safeCollect(crossinline action: suspend (T) -> Unit) {
  collect {
    coroutineContext.ensureActive()
    action(it)
  }
}

@qwwdfsad qwwdfsad added the flow label Jan 15, 2020
@elizarov
Copy link
Contributor

This is a duplicate of #1265

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants