When is it correct to use repeatOnLifecycle using coroutines Flows?

69 views Asked by At

From coroutines official documentation we noticed this warning about the correct usage of coroutines.

Warning: Prefer collecting flows using the repeatOnLifecycle API instead of collecting inside the launchWhenX APIs. As the latter APIs suspend the coroutine instead of cancelling it when the Lifecycle is STOPPED, upstream flows are kept active in the background, potentially emitting new items and wasting resources.

To comply with this warning, we made this utility function:

inline fun AppCompatActivity.launchAndRepeatWithViewLifecycle(
    activeState: Lifecycle.State = Lifecycle.State.STARTED,
    coroutineExceptionHandler: CoroutineExceptionHandler = getDefaultExceptionHandler(),
    crossinline block: suspend CoroutineScope.() -> Unit
): Job =
    lifecycleScope.launch(coroutineExceptionHandler) {
        lifecycle.repeatOnLifecycle(activeState) {
            block()
        }
   }

Using this function, when the Activity goes into onStop, it stops following the flow. The Activity re-joins the flow at each onStart.

Here are two use cases:

In the first one we use a Flow. We have this kind of flow when it is related to the View Status (Loading, Content, NetworkError, etc..) With this kind of flow, the use of this utility function generates unexpected edge cases. For example when the activity rejoins the flow, it re-collect the previous status and tries to re-populate the view. We avoid this, thanks to some recyclerView logics.

In the second use case, we use a Flow(replay = 0) We have this kind of flow when it is related to user Actions (ClickButton, BackPressed, etc..). In this situation the use of this utility function seems to be correct, because we don't need to follow the flow when the view is not visible to the user and, thanks to replay = 0, the view does not re-collect previous values when onStart is called.

In summary, the questions are:

  • When do we have to use this utility function?
  • The correct use of this function seems to be in the first case, because only in this case we could have a change of status when the view is not visible (causing a potential crash), but it is the problematic case. So we have to use this function only when we have flow related to DB or related to connection issues?
  • In the second use case, is the usage of this utility function correct?
0

There are 0 answers