Compose Theme: How to change light and dark mode dynamically with SharedFlow

3 min readJul 24, 2022
Photo by Rami Al-zayat on Unsplash

In this article I want to propose a method to change from light mode to dark mode and vice versa using SharedFlow.

Part I: Animated colors switching from light to dark mode

Flow and SharedFlow

First let’s look at what a Flow is, let’s read the documentation:

In coroutines, a flow is a type that can emit multiple values sequentially, as opposed to suspend functions that return only a single value. For example, you can use a flow to receive live updates from a database.

Flows are built on top of coroutines and can provide multiple values. A flow is conceptually a stream of data that can be computed asynchronously. The emitted values must be of the same type. For example, a Flow<Int> is a flow that emits integer values.

What about SharedFlow ? It is a Flow API that enable flows to optimally emit state updates and emit values to multiple consumers.

As an example, you could use a SharedFlow to send ticks to the rest of the app so that all the content refreshes periodically at the same time.


SharedFlow and Theme

First, we create our SharedFlowwhich we will use to notify the selected mode change:

Where Theme is an Enum with the theme modes.

Use cases

Now, following Android architecture with Hilt, we define in the domain model two use cases to emit and read the SharedFlow


With GetThemeUpdateUseCase we ask the Flow<Theme> value and with PublishThemeUpdateUseCase we emit the Theme value.


In the ViewModels we use the use cases above, in one of them we emit the Theme value selected from a DropdownMenu

Selecting the light or the dark mode we call publishThemeUpdateUseCase with the relative theme selected.

In the other ViewModel we collect the Theme value and update a State variable to observe the change in the Compose screen.

Update Theme

Finally, in the MainActivity we observe the theme state value to update the MaterialTheme , passing the value to our ComposeFuctionsTheme

In the following repository, you can find the completed runnable implementation, also we used DataStore to save the value locally:

You can find a branch with the implementation of Material 3.

Thank you, I hope you enjoyed reading it.