简体   繁体   中英

Kotlin coroutines Flow is not canceled

I have a UseCase class with method that returns Flow

fun startTimeTicker(startTime: Long) = flow {
    val countdownStart = System.currentTimeMillis()
    for (currentTime in countdownStart..startTime step ONE_SECOND_MILLIS) {
        .... irrelevant ...
        emit("Some String")
        delay(ONE_SECOND_MILLIS)
    }
}

I'm collecting emmitted date in ViewModel like this

private fun startCollecting(startTime: Long) = launch {
    matchStartTimerUseCase.startTimeTicker(startTime).collect {
        _startTimeCountdown.postValue(it)
    }
}

and my fragment is observing LiveData and displaying values. It works as expected until the time I leave the screen. As launch is called with coroutineScope of ViewModel shouldn't it get canceled and not emit values anymore?

Scope of ViewModel is implemented in BaseViewModel from which my ViewModel extends like this:

abstract class BaseViewModel( private val dispatcherProvider: DispatcherProvider ) : ViewModel(), CoroutineScope {

override val coroutineContext: CoroutineContext
    get() = job + dispatcherProvider.provideUIContext()

private val job = SupervisorJob()

override fun onCleared() {
    super.onCleared()
    job.cancel()
}

}

Am I forgetting to add some custom cancellation logic or missing something other?

If scope your ViewModel is Activity's life cycle ViewModelProvider(requireActivity()).get(YOUR_VIEWMODEL::class.java) then onCleared won't be called unless your Activity gets destroyed, but not with rotation changes.

First, make sure that onCleared() is called, if it's not called you can call it any life cycle method of Fragment or Activity.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM