ProAndroidDev

The latest posts from Android Professionals and Google Developer Experts.

Follow publication

Bridging StateFlow and Jetpack Compose State: A Cleaner Architectural Approach

Ioannis Anifantakis
ProAndroidDev
Published in
5 min readDec 6, 2024

Managing UI state in Android apps often involves a delicate balance: Compose’s built-in state (mutableStateOf) makes it incredibly easy to keep your UI updated, while Kotlin’s StateFlow offers powerful, testable, and thread-safe reactive data streams. The challenge arises when you try to combine these approaches. While it’s simple to drop collectAsStateWithLifecycle() calls into your composables, you end up repeating code and sprinkling collection logic throughout your UI layer.

In this article, we’ll show you a step-by-step method to leverage both Compose’s ergonomic property delegation and StateFlow’s reactive capabilities. We’ll start simple, then scale up to more complex scenarios, all while ensuring our composables remain focused on rendering and not on state management details.

Starting Simple: Compose’s Built-In State

Consider a basic ViewModel controlling a splash screen:

data class MainState(
val showSplash: Boolean = false
)

class MainViewModel : ViewModel() {
var state by mutableStateOf(MainState())
private set

init {
viewModelScope.launch {
// Show splash for a couple of seconds
state = state.copy(showSplash = true)
delay(2000L)
state = state.copy(showSplash = false)
}
}
}

In your UI, this is straightforward:

@Composable
fun MainScreen(viewModel: MainViewModel = viewModel()) {
val state = viewModel.state

if (state.showSplash) {
SplashScreen()
} else {
MainContent()
}
}

Here, it feels natural: the composable just reads viewModel.state. Compose takes care of recomposing when state changes—no extra hoops to jump through.

Introducing StateFlow for More Complex Logic

As your app grows, you may need reactive streams that are testable, concurrent-safe, and easily combined. StateFlow excels here:

class MainViewModel : ViewModel() {
private val _state = MutableStateFlow(MainState())
val state: StateFlow<MainState> = _state

init {
viewModelScope.launch {…

Create an account to read the full story.

The author made this story available to Medium members only.
If you’re new to Medium, create a new account to read this story on us.

Or, continue in mobile web

Already have an account? Sign in

Responses (1)

Write a response