Categories
android blog kotlin

A basic comparison of LiveData, StateFlow, and SharedFlow

Why do we need these classes?

For one simple reason, reactivity. It’s very easy to keep the UI in sync when we don’t have to pull data from the View, instead, View is updated every time there is a change in the screen state. In a sense, this is an idea of unidirectional data flow. There is a single source of truth and everything is reacting to changes in the source. But we need more than that on mobile, we need to stop listening to updates when Views go out of scope to avoid null pointer exceptions. So we need a nice reactive pattern but we also need the ability to automatically unsubscribe from the updates if a particular Activity/Fragment is no longer visible. LiveData is essentially that. StateFlow and SharedFlow are different bests, and they are more like RxJava observables, (in Kotlin terms flow) but can be retrofitted to do the same thing.

Two fundamental types of streams 

If we step back and think about a stream of data, we fundamentally need two different cases, one where we want to grab every event and we don’t want the stream to start before we are ready, aka cold stream. The alternative to this is a hot stream, where we don’t care about consumers of the data, we are emitting values independently. It’s already clear which stream we would prefer for state and which for, let’s say error handling or one-off toast. StateFlow is a hot stream with the last value stored, any new subscriber will be immediately notified of the last value that a StateFlow emitted, making it ideal for keeping track of states in an app screen. Why is that the case? Well, we want to be able to always get the latest state for the screen so we can render the correct UI. Otherwise, we might render an outdated state, or we might be missing state till the next update comes. In contrast to that, let’s say we want to show an error message, we don’t wanna repeat the last error message every time we start listening for error messages. It makes sense to only display the same error message once.

Those are two fundamental use cases for mobile apps. So in a general sense, we are interested in hot streams, since we want to have the latest state processed regardless of the state of a particular Activity/Fragment.

LiveData is not enough

Didn’t we already have this with LiveData? It keeps the last value, it also updates its subscribers every time there is a new state, why do we need State or SharedFlow? Well, for starters LiveData was not suitable for errors and one-off message handling. In the end, a special Event data structure was needed to keep track of processed events. Another issue with LiveData is the lack of operators that it supports, operators like reply, debounce, filter, etc. It was a great solution for Android, but with StateFlow it kinda lost its place. StateFlow is an almost drop-in replacement for LiveData, and it’s supported with Kotlin out of the box. 

StateFlow

It can be called LiveData on steroids. It has similar properties in that it always has the last state saved but it also provides a rich API of operators. One shortcoming of StateFlow is that it does reply last event to new subscribers, which is ideal for state management, but not for one-off events. That is where SharedFlow comes in. 

StateFlow has a value property that can be read at any point in the life of a StateFlow, which is very handy when we need to access the latest state without subscribing. Because it has .value, StateFlow does require an initial value to be provided at the start. This is a bit cumbersome sometimes, but on the other hand, it’s nice to have null/nonnull .value property to be accessed at any point in the future.

Sharedflow

This is a hot flow that just emits values regardless of new subscribers. It can be configured to behave as StateFlow (practice question, how?) but in general, it does not have an initial value and it does not have .value property that can be accessed. By now, you should get a sense that SharedFlow is perfect for one-off events, where we don’t want to keep track of old states, we just wanna listen to new events and handle them as they go. 

Summary

So, how to pick a perfect Observable data structure for an Activity/Fragment? In simple terms, StateFlow is the default choice, if you get the feeling that there is a need for a one-off event, then SharedFlow is the way to go.

In the next couple of articles, we will go a bit more in-depth on StateFlow and SharedFlow. Happy coding!

Categories
blog kotlin

Quick introduction to Kotlin coroutines part 1

Motivation

So first, let me start this article by saying that I spent few years developing Android apps in Java, and the one thing that I used to do frequently was to separate layers of abstraction with interfaces. And for example in the networking layer, I end up writing lots of interfaces that declare methods, with a listener parameter, and this listener will implement some onSuccess and onFail methods. What this leads to is lots of nested callbacks where I go few layers deep into callbacks and onSuccess and onFail blocks, something like the code below.
https://gist.github.com/abdurahmanadilovic/ea31ce7213584e170d35ce7747f58310
https://gist.github.com/abdurahmanadilovic/3f40ec45594c135b1572406256e5d073
Then Kotlin came along, got supported by Google officially and suddenly, everyone went mad, and for a good reason, it is a modern swift like, compiled, language, which is a huge step up from the Java world. And one thing caught my eye when I first read through the Kotlin documentation, Kotlin coroutines. I thought, well this for me, the one thing I can use right now to avoid my callback hell problem. So I jumped straight into it. Here is my journey to understanding what Kotlin coroutines are.

Asynchronous code as a synchronous code

The header above is the essence of what coroutines are, it is a way to declare a block of code in which every line suspends execution of the block, what does that mean? Well, you simply don’t have to provide a callback for long-running functions, you just add that function to a coroutine and the coroutine will suspend its execution until that method returns hence no more callbacks!
Look at the code below:
https://gist.github.com/abdurahmanadilovic/2305c78e672e89aef6d62aaf1daae314
This is my interface for the data storage contract in Kotlin, no listener interface needed, you will notice the suspend keyword in front of all methods, that is a special Kotlin syntax to indicate this function should be run from a coroutine block or another suspend function, basically anything that involves a network call or a CPU intensive task should be placed inside suspend functions and then consumed from a coroutine block.

Coroutine builders

If we want to call our suspend function, we need to pass it to the coroutine builder, which will do the heavy lifting for us, and ensure that the code inside that builder will run on a thread of our choice, for example, let’s use launch coroutine builder:
https://gist.github.com/abdurahmanadilovic/4fe458ca10392af7ca20f8e67aa8b763
That’s it, you simply consume your suspend function inside the launch block and you are good to go.  Every time a suspend function is encountered, the execution of this coroutine block suspends, waiting for the function to return. Any code above our getStringValue method call will be executed first, then our function, then the rest of code below, no callbacks! So on which thread will the above launch block execute? Obviously, we want it to execute on a background thread and we want to update the UI with values from our suspend functions.

Coroutine context

Every coroutine builder can have a context in which to run, the main thread, or some other thread, if no context is specified, like the example above, it’s the CommonPool of threads, meaning it will run on a separate thread from the main thread of the app. So if the code above is running in the background thread, how to update the UI then? To update the UI there is one more step that needs to be done, and its another launch block with a coroutine context specified, like the example below:
https://gist.github.com/abdurahmanadilovic/5d2b59a2a0e19c36816e918b4d7d2fdf
Everything inside the second launch will use the main thread event dispatcher, that will post our update on the main thread. What is cool about this is that the second launch block will also wait for the code above to execute and once it does execute, the value variable will be set and we can safely update our UI. Coroutine context is simply a coroutine dispatcher, which controls on what thread the coroutine block is running.

Coroutines are lightweight threads

Coroutines run on threads and can suspend its execution without blocking the thread it runs on, so the thread execution is not tied to the coroutine execution, they operate separately. If you think about it, callbacks are almost the same thing, they suspend execution and continue once the result is available, but have a boilerplate syntax and require you to repeat yourself everytime you want to suspend an execution.

Launch vs Run coroutine builder

One problem with nesting coroutines is that every coroutine block will have its own execution line, meaning the second coroutine block will not suspend the parent coroutine. There is a better way of writing the code above, since getStringValue  function returns a value, we can use a run coroutine builder to return a value from a suspend function, hence we can start on the main thread, and invoke our getStringValue function inside a background thread, the other way around from the example above.
https://gist.github.com/abdurahmanadilovic/e744c4726880f1f1a320bbb39d7c576c
The main difference between launch and run coroutine builder is the return value, launch has none while run has, so in this case, we will assign our variable value to whatever the result value of the run block is.
I specified a dispatcher for run block intentionally since nested coroutines take the parent coroutine context if not specified, and we do not want that in this case, we want the run block to execute on a background thread.
I believe this is all you need to know to start playing around with coroutines, don’t hesitate to open android studio and write some coroutines!

Further reading

Coroutines can do much more if you need it, there are many different coroutine builders, channels, synchronization options etc. The best introduction to coroutines is the official Kotlin coroutines guide on Github, don’t hesitate to read it, you will find lots of gems in there.

Dependencies

To use coroutines in your project, you need a couple of additions to your build grade file, mainly these two lines:
https://gist.github.com/abdurahmanadilovic/4e18e8cd59710f16281e2169ba078146
The coroutines-android dependency is for the special UI context that can be passed to coroutine builders that uses the main thread dispatcher to dispatch events on the main thread.
Then you have to tell Gradle that we will use coroutines in the app by adding these lines to the app build Gradle file:
https://gist.github.com/abdurahmanadilovic/d7c8fa4776c8055c636cf73a10e0e604

Github sample project: Fibonacci counter

I wrote a simple Android app in Kotlin, that implements a Fibonacci counter with coroutines. Check it out on Github, clone the repository and play with it and most importantly have fun!

Conclusion

This is a part one of two-part series, check out part two of the series.