Thanks to the Jetpack Compose, building Android UI is much easier than it used to be. Within composable functions, we can do almost whatever we want. However, it is a good practice to use view models as state holders as well as sources of access to business logic. The simple example will be like this:
Whenever the ExampleViewModel updates its uiState, it's notified to ExampleScreen and ExampleScreen triggers recomposition.
That looks good. But how about this case, a view model wants to pass data to UI and recomposes it, but the data should not be persisted as a state.
For example, let's think of this screen. When one of those text buttons is tapped, the screen notifies it to a view model. Then, the view model processes something related to domain logic and publishes the URL. In the end, the web view loads the URL and shows the content on the screen.
In this case, we don't want to hold the URL as a state because, otherwise every time recomposition is triggered, the web view loads the same URL again and again. Instead, the view model should notify the URL only once and doesn't save it anywhere.
How do we achieve it? To address this, we can use SharedFlow which is Kotlin's built-in hot flow mechanism. Let's take a look at how it will be done.
In the below code snippet, the first data class is nothing special. When a text button is clicked, one of the enum objects will be passed to the EmbeddedWebViewViewModel.loadUrlFor(). and the view model does some business logic and emits the url through the UiEvent instance.
And on the screen, shared flows can be collected as a state. It means that every time the shared flow emits data, it triggers recomposition to update UI.
This is how it works. To store view state, we can use MutableState and, for one-time requests to the view, we can use SharedFlow :)