preface

The shareIn and stateIn operators of Flow can convert a Cold Flow to a Hot Flow: it can broadcast data received from upstream Cold Flow to all subscribers. It is often used to improve performance and even has an internal caching mechanism.

Cold Flow generates data as soon as it is subscribed or observed. Usually the subscriber can observe all the data. Hot Flow, on the other hand, remains active and may emit data whether or not a subscriber subscribes.

In this blog, you can familiarize yourself with the shareIn and stateIn operators through examples. You’ll learn how to configure them to meet some usage scenarios, and you’ll learn how to avoid common pitfalls.

Underlying data producer

Continue the example from the previous article. The underlying Flow producer emits location updates. It is a Cold Flow, implemented with callbackFlow. Each subscriber to subscribe to, no trigger Flow producers block, leading to each time to create a new callback added to FusedLocationProviderClient

Let’s look at how the shareIn and stateIn operators can be used to optimize the above code for different scenarios.

shareIn or stateIn?

The stareIn operator returns a sharedFlow, while stateIn returns a StateFlow.

Detailed information can check the document here: developer.android.com/kotlin/flow…

StateFlow is a special SharedFlow class. StateFlow is a SharedFlow derived class. The behavior of StateFlow is similar to that of LiveData. The last status is transmitted to the subscriber.

The biggest difference between the two is that StateFlow allows you to access the status of the last launch. SharedFlow is not allowed.

If you’re familiar with LiveData or RxJava BehaviorSubhect, you’ll instantly understand StateFlow’s behavior.

Improve performance

These apis can improve performance by sharing the same Flow instance. When a subscriber subscribes, the flow is not created multiple times, and the data producer is not forced to execute an internal block each time, as was the case above.

In the following example, LocationRepository consumes the flow of the locationsSource and converts it into a shared flow object so that subscribers can subscribe to the same flow.

WhileSubscribed strategy is to disconnect upstream flows when no subscribers are available to avoid wasting resources. But sometimes the view layer may have configuration changes caused by system behavior. This triggers unsubscribe and re-subscribe to the upstream Flow. The official recommendation is to use the WhileSubscribed(5000) strategy. If there is no subscriber within 5 seconds, it will be cancelled, which is a good way to avoid the waste of resources caused by configuration changes.

Event caching

In this case, our requirements have changed. There are two requirements:

  1. We expect subscribers to receive location updates all the time
  2. New subscribers receive the last 10 location data.

Width = “auto” height = “auto” SRC = “raw.githubusercontent.com/xiaojinzi12…” />

We can use the replay parameter and set it to 10 to cache the last 10 positions. When a subscriber subscribes, they receive these 10 values. To keep the underlying Flow producer active. We can use the strategy of SharingStarted. 15. Even without any subscribers.

Data cache

Now the new requirement is that we only need to receive the last piece of data when the subscriber subscribes. At this point we can use the StateIn operator.EmptyLocation is a default value that is passed. Because StateFlow requires a default value.

Problems to avoid

Never use shareIn or stateIn in a method to create a new Flow. This will cause you to create an infinite number of Hot flows that will be destroyed when the corresponding scope cancels. The error demonstration is as follows:

conclusion

The shareIn and stateIn operators can improve performance by turning Cold Flow into Hot Flow. Be careful not to use the stateIn and shareIn operators to create Hot flows in multiple-execution methods or blocks of code. This can lead to a serious waste of resources.

Read all read, pay attention to my public number