Lifecycle for Android Developers (Part 2)

Dinorah Tovar
5 min readApr 11, 2022

--

Under the hood of LifecycleOwners, collection, and events

Here is the list of the blogs in this series:

Flows

This is the second part of this series “Lifecycle for Android Developers” for this part, we will discuss the power of LiveData and Flows, especially how they work, but also, we will discuss the pitfalls of both of them (yes, flows, have pitfalls)

LiveData

LiveData works in parallel to a given lifecycle, so this means that a LiveData will have to be bound to LifecycleOwner and to an Observer, so every time the LiveData gets any modifications in the wrapped data this will get notified. Usually, when we are using a LiveData we may end up using something like this.

The function observe will add the given observer to the observer's list, given the lifespan of the owner — in this case, the owner will be this — which can only be used when the observer is used on an Activity — for a Fragment we need to use viewLifecycleOwner

LiveData is bound to the Main Thread too, and this function observe explains quite well the functionality behind the space and consumption process of a collection of data.

First thing first!
LiveData events will get dispatched on the Main thread as we can see in the first line and the assertion later on in line 3. LifecycleOwner is considered active if its state is Started or Resumed the observer will only receive events if the owner is in this state, once the Lifecycle reaches the state of Destroyed, the observer will automatically be removed.
It also helps us to not add observers in two different lifecycle states as mentioned in the exception in line 11.

LiveData did many things right and others not so right — for example, the LiveData will only receive events when the LifecycleOwner is in some specific states, making this aware of the changes in the Lifecycle of an application, it will also trigger the latest changes easily!
This also means that LiveData keeps a strong reference to the observer and the owner, making LiveData 100% thigh to Android

Flows

So, imagine that you may want to clear your app architecture and left only Android components in your top layers — with LiveData this will be not possible, you may end up needing it flows on your Repository layers and then making a transformation to LiveData — something like the next image:

However, if we decide to use Flows, this last transformation may not be necessary — we can use Flows from beginning to end in all our processes; for the Repositories, we can use regular flows and for the Presentation layer, we can use SharedFlow and Stateflow.

SharedFlow

SharedFlow is a special type of Hot Flow, that shares emitted values among all the possible listeners, also known as collectors, making these collectors aware of the emitted values, an active collector is also known as a Subscriber
One of the characteristics of a hot flow is that this maintains an active instance, even when there are no collectors.
ShareFlow has a couple of important characteristics that make it unique and powerful, for example:

  • Strategy and configuration for replay and buffer overflow
  • Subscribers of a SharedFlow can be canceled — making it disposable and memory aware of the environment they are performing
  • SharedFlow has a read-only, making Mutability simpler

There are two interfaces for SharedFlow and MutableSharedFlow, that show some of the parts this flow has, for example, these flows will keep in memory a specific number of the latest values emitted using Replay Cache, so every new subscriber will get these values, plus, the new emitted values, the max capacity in this buffers is the specified of the replay parameter, which by default is equal 0

A MutableSharedFlow is a mutable SharedFlow that provides functions to emit values to the flow, count the subscribers that are listening to the flow, and has the capability of resetting all the cache!
You may notice, that this type of Flow, does not have any direct access to the value, however, Stateflow has a concept for this

Stateflow

Conceptually Stateflow is similar to SharedFlow, which solves a very specific purpose, of sharing a state, that makes it look a little bit like a LiveData

Stateflow, end up having access to a value, but only one value at any given time, so this makes a Stateflow aware of only the latest value on the subscription, making this a Conflated Value

Memory is one of the biggest concerns when Android Developers start working with Flows, a couple of years the memory was a concern using Channels, however, Stateflow is optimized for memory verification and allocation freedom. However, Flow is not lifecycle aware, making them capable of summiting data to the subscribers at any given type, for example, when a device is getting rotated, or day to day scenarios, making Flow Collection a problem in the UI Thread — however, we have a solution that we will discuss in the next part of this series

This is all for this part of the series. For the next part, we will discuss the Collection of Flows in the UI thread and we will address the problem that has when consuming them in a View.

If you need help, I’m always happy to help, you can find me here:
Medium as Dinorah Tovar
Twitter as
@ddinorahtovar
StackOverflow as
Dinorah Tovar

--

--

Dinorah Tovar

Google Developer Expert on Android | Doing Kotlin | Making Software 24/7 | Kotlin Multiplatform | She/Her | Opinions are my own, and not my employer