Loading...
Home
  • Tech Blogs
  • Videos
  • Conferences
    • Droidcon News
    • Upcoming Conferences
    • Become a Partner
    • Past Events
    • Keep Me Informed
    • Diversity Scholarships
  • Community
    • droidcon Team
    • How to Hold a Droidcon
  • Android Careers
Sign In

Global CSS

 

Going deep on Flows & Channels — Part 5: StateFlows

 

 
Julián Ezequiel Picó
Android Dev
Published: July 31, 2020
Tweet
Share
 

Picture of Baskin Creative Studios from Pexels

 

Spanish version

This text is based on 1.3.7 version of kotlinx.coroutines library

 

Welcome to the last (at least, for now) article of this series, where we are going to discuss what is a StateFlow and its behaviour.

You can see some examples by checking the GitHub Repository. There, you will see how a StateFlow is implemented and how it works. Now that you will have a basis about Kotlin Streams API, you can fork and modify all the examples that you have there 😃

Remember that this article belongs to a series:

  • Part 1: Cold & Hot Streams.
  • Part 2: Flows.
  • Part 3: Channels.
  • Part 4: BroadcastChannels.
  • Part 5: StateFlows and conclusions.

Let’s go with part five: StateFlows!

 

StateFlows

What is a StateFlow?

We know what Flows, Channels and BroadcastChannels are, and we have all the stream types implemented within them. So, what's a StateFlow?

Well, basically it's a new flow implementation, which is designed to make a flow stateful, to keep an updatable state over time. With this, we are saying that it can have a state and it doesn't depend on a specific context, like a normal flow implementation.

As a Flow, StateFlow is an interface too. Also, we have a mutable version of StateFlow, represented by the MutableStateFlow interface.

 

 

We can see that actually a StateFlow is a Flow with a value. The MutableStateFlow makes that value mutable.

 

Creating StateFlows

A StateFlow cannot be created directly, because it’s an interface and we cannot instantiate an interface.

Instead, there is a factory function (yes, factory functions for the win) to create a MutableStateFlow.

 

 

And that's it!

 

Exposing the StateFlow

One of the main advantages of a StateFlow is that it can be exposed in two different modes, with only one instance.

 

Reactive mode

If we need to access the value in a reactive way, it can be exposed as a Flow. So if we want, for example, to collect all the changes to the StateFlow's value, we can collect them in the same way we did with Flows.

 

 

Non-Reactive Mode

If we need to get the value of the StateFlow directly, in a non-reactive way, as it exposes its value, we can access just by calling its getter.

 

 

Emitting and Updating values

As we can imagine, an update to StateFlow's value triggers an emission of the Flow.

How does StateFlow notifies its listeners that its value has changed? Well, all the updates are performed in a Conflated way: it works like a Conflated Channel, where the value in the buffer is always the latest sent to it, and the values that weren't received by someone got lost.

So, a slow collector will omit an update that happens faster than the processing of the previous value. But, as it's a conflated emission, the collectors will always have the last value emitted.

Maybe this mechanism of emissions is one of the reasons why the StateFlow is intended to replace the ConflatedBroadcastChannel. It emits like a Conflated Channel, and anyone who has a reference to the StateFlow can read its value, so it has a multicast feature.

How to change StateFlow's value? Just modifying it with the setter:

 

 

What's the difference with Flows?

There are several differences that we can mention. The most important ones are:

  • Multicast feature: it can have more than one collector, and it can emit the value to all of them.
  • Non-reactive Flow: we can access the StateFlow's value without performing a collection. And we can access to it as fast as we want, because we don't have to wait until the next emission.
  • Emit from wherever: we can modify the StateFlow's value using its mutable version just by having its reference. So, if we have the reference, we can emit, simple as that.
  • Scope: StateFlow doesn't have an execution context by itself. If we remember, the Flow scope is the CoroutineScope that triggers its execution. Here we don't have that constraint (or benefit?).

 

What's the difference with ConflatedBroadcastChannels?

Also, there are several differences with that we can mention, even if they're too similar (because, conceptually, they're the same). For me, the most important ones are:

  • The Flow API is simpler to use than the Channel API, so we have a component that works just like a Channel, but with a much more simpler and powerful API.
  • The StateFlow always has a value, unlike a Channel. We cannot instantiate a StateFlow without a value.
  • We have a clear mutable/immutable separation. With Channels, anyone that has its reference can send values, but with StateFlows we can expose the immutable version to the outside and no-one will perform an emission, because they won't be able to do it.
  • StateFlows emit based on equality, Channels do it based on reference. This means that if we emit the same value (not the same object), that value will be omitted. To get more information about how equality works, check this link.
  • The StateFlow cannot be closed or represent a failure, because the API doesn't allow it. That's a huge difference with Channels, where we can just cancel or close them.

 

Using the StateFlow

There isn't too much to say here, because it inherits the Flow interface to collect the values emitted, so we can use it as a Flow. Anyway, I will mention some stuff that you've to consider when using the StateFlow:

  • StateFlow has a last value, so we'll always receive at least one emission.
  • The emission can be activated before someone subscribes to the StateFlow.
  • We have a multicast stream.

And that's all for StateFlows!


Conclusions

After five articles, I don't want to lose the chance of giving my opinion about the different APIs and which of them are more convenient to use.

First of all, I think that these APIs are very helpful for almost all the use cases that require some reactive flows. With all the components that we've reviewed, we can be sure that, if we want, we can implement any stream flow in our applications or systems. So, good for us that we can depend only on the programming language to do this stuff!

Second, I think that you've already noticed that there is no such cold/hot concern separation. Furthermore, in my opinion, it's not so important to know if you have to choose a cold or a hot stream, instead, you must know how the Kotlin APIs work and then decide which of them will help you fulfilling your goal. The most important things to understand are the purposes and the behaviours, and not the definitions.

Lastly, if you're developing for the Android platform, I'll recommend you to avoid Channels API. You can use Flow and StateFlow to develop almost any feature, and they're much more simpler to use than Channels. So, if you are thinking about implementing some Channel's feature, be sure that StateFlow it's not what you need.


The end

So, we are in the last section of the last article. Thank you all for reading, sharing and clapping the articles on this series.

I really enjoy writing them, and I really hope that they will be helpful and useful for all the developers who are diving in the world of the streams.

I'll be trying to stay up to date with the new kotlinx coroutines libraryversions, and to update the articles according to those releases.

Thanks again and see you later!


Special thanks to the MediaMonks Android team that gives feedback.

 

 

 

Tags: Android, Kotlin, Flow, Android App Development, AndroidDev

 

View original article at: 


 

Originally published: July 13, 2020

Android News
Our Engineering Roadmap
Our Engineering Roadmap

By Mark Ng

We just completed our engineering road map for our Android apps at Australia Post. Each year we get together and try to decide on what we are going to do from an engineering perspective for the next 12 months. Each team gets to decide on what should be done now, what they want to complete by the end of the year and whats on the horizon for next year.

By ProAndroidDev -
Android News
Android Activity Lifecycle considered harmful
Android Activity Lifecycle considered harmful

By Eric Silverberg

The Android activity lifecycle is one of the first architectural concepts learned by a new Android developer. Ask any Android dev and they’ll likely all have seen this handy diagram from Google: 

By ProAndroidDev -
Android News
Our Safe Approach to Android Jetpack Navigation in a Multi-Modular App
Our Safe Approach to Android Jetpack Navigation in a Multi-Modular App

By Alejandro Weichandt

It has been a year since we started working on the Android version of the mobile app at Sync. During that year, we faced more than once that moment when we had to choose which path to follow on an Architectural decision. This story is about Navigation.

By ProAndroidDev -
Android News
Custom KotlinX Serializers
Custom KotlinX Serializers

By Jobin Lawrance

Let’s say we have a third-party class that we are using as a type in one of our data class that we want to be serialized, then we have to write a custom serializable for @Serializable to work.

 

By ProAndroidDev -
droidcon News

Tech Showcases,

Developer Resources &

Partners

/portal/rest/jcr/repository/collaboration/Groups/spaces/droidcon_hq/Documents/public/home-details/EmployerBrandingHeader
EmployerBrandingHeader
https://jobs.droidcon.com/
/portal/rest/jcr/repository/collaboration/Groups/spaces/droidcon_hq/Documents/public/employerbranding/jobs-droidcon/jobs.droidcon.com
jobs.droidcon.com

Latest Android Jobs

http://www.kotlinweekly.net/
/portal/rest/jcr/repository/collaboration/Groups/spaces/droidcon_hq/Documents/public/employerbranding/kotlin-weekly/Kotlin Weekly
Kotlin Weekly

Your weekly dose of Kotlin

https://proandroiddev.com/
/portal/rest/jcr/repository/collaboration/Groups/spaces/droidcon_hq/Documents/public/employerbranding/pad/ProAndroidDev
ProAndroidDev

Android Tech Blogs, Case Studies and Step-by-Step Coding

/detail?content-id=/repository/collaboration/Groups/spaces/droidcon_hq/Documents/public/employerbranding/Zalando/Zalando
/portal/rest/jcr/repository/collaboration/Groups/spaces/droidcon_hq/Documents/public/employerbranding/Zalando/Zalando
Zalando

Meet one of Berlin's top employers

/detail?content-id=/repository/collaboration/Groups/spaces/droidcon_hq/Documents/public/employerbranding/Academy for App Success/Academy for App Success
/portal/rest/jcr/repository/collaboration/Groups/spaces/droidcon_hq/Documents/public/employerbranding/Academy for App Success/Academy for App Success
Academy for App Success

Google Play resources tailored for the global droidcon community

Follow us

Team droidcon

Get in touch with us

Write us an Email

 

 

Quicklinks

> Code of Conduct

> Terms and Conditions

> How to hold a conference

> FAQs

> Imprint

Droidcon is a registered trademark of Mobile Seasons GmbH Copyright © 2020. All rights reserved.

powered by Breakpoint One