Original topic:

A safer way to collect flows from Android UIs

(Topic created on: 03-29-2021 07:31 AM)
Expert Level 5

In an Android app, Kotlin flows are typically collected from the UI layer to display data updates on the screen. However, you want to collect these flows making sure you’re not doing more work than necessary, wasting resources (both CPU and memory) or leaking data when the view goes to the background.

In this article, you’ll learn how the LifecycleOwner.addRepeatingJob, Lifecycle.repeatOnLifecycle, and Flow.flowWithLifecycle APIs protect you from wasting resources and why they’re a good default to use for flow collection in the UI layer.



Wasting resources

It’s recommended to expose the Flow<T> API from lower layers of your app hierarchy regardless of the flow producer implementation details. However, you should also collect them safely.

A cold flow backed by a channel or using operators with buffers such as bufferconflateflowOn, or shareIn is not safe to collect with some of the existing APIs such as CoroutineScope.launchFlow<T>.launchIn, or LifecycleCoroutineScope.launchWhenX, unless you manually cancel the Job that started the coroutine when the activity goes to the background. These APIs will keep the underlying flow producer active while emitting items into the buffer in the background, and thus wasting resources.

Note: A cold flow is a type of flow that executes the producer block of code on-demand when a new subscriber collects.

For example, consider this flow that emits Location updates using callbackFlow:


Note: Internally, callbackFlow uses a channel, which is conceptually very similar to a blocking queue, and has a default capacity of 64 elements.