2
votes

In RxJava there is the valve operator that allows to pause (and buffer) a flow and resumes the flow again (and also emit the buffered values as soon as it's resumed). It's part of the rx java extensions (https://github.com/akarnokd/RxJavaExtensions/blob/3.x/src/main/java/hu/akarnokd/rxjava3/operators/FlowableValve.java).

Is there something like this for kotlin flows?

My use case is that I want to observe a flow inside an activity and never lose an event (like I would do it with LiveData e.g. which stops observing data if the activity is paused). So while the activity is paused I want the flow to buffer observed values until the activity is resumed and emit them all as soon as the activity is resumed.

So while the activity is created (until it is destroyed) I want to observe the flow BUT I only want to emit values while the activity is active and buffer the values while it is not active (but still created) until it gets active again.

Is there something to solve this or has anyone ever written something to solve this?

2

2 Answers

0
votes

A combination of Lifecycle.launchWhenX and a SharedFlow should do the trick. Here's a simple example using a flow that emits a number every second.

// In your ViewModel
class MainViewModel : ViewModel() {
    val numbers = flow {
        var counter = 0
        while (true) {
            emit(counter++)
            delay(1_000L)
        }
    }
        .shareIn(
            scope = viewModelScope,
            started = SharingStarted.Lazily
        )
}
// In your Fragment.onViewCreated()
viewLifecycleOwner.lifecycleScope.launchWhenStarted {
    viewModel.numbers
        .collect { number ->
            Log.d("asdf", "number: $number")
        }
}

This works because Lifecycle.launchWhenStarted pauses the coroutine when the Lifecycle enters a stopped state, rather than cancels it. When your Lifecycle comes back to a started state after pausing, it'll collect everything that happened while in the stopped state.