Jetpack Compose Side Effects — Complete Guide
In this tutorial, you'll learn about Jetpack Compose Side Effects. We cover key concepts, practical examples, and best practices to help you understand and apply this topic effectively.
The Problem
Your network call runs on every recomposition, the timer restarts constantly, or the Firebase Observer accumulates multiple subscriptions.
Wrong Approach ❌
@Composable
fun BadLoader() {
// Runs on EVERY recomposition — infinite loop!
val result = viewModel.loadData()
// Side effect without key — restarts on every recomposition
LaunchedEffect(Unit) {
viewModel.loadData() // Okay, but...
}
}
@Composable
fun LeakyObserver() {
// Added every recomposition — never disposed
DisposableEffect(Unit) {
firestore.addSnapshotListener { /* callback */ }
onDispose { } // Empty! Never removes listener
}
}
Output: Network call floods the server. Memory leak from unremoved listeners.
Right Approach ✅
@Composable
fun GoodSideEffects(userId: String) {
// Key changes when userId changes — restarts the coroutine
LaunchedEffect(userId) {
viewModel.loadData(userId)
}
// Properly cleaned up
DisposableEffect(userId) {
val listener = firestore.document("users/$userId")
.addSnapshotListener { snapshot, _ -> /* handle */ }
onDispose {
listener.remove() // Cleanup!
}
}
// SideEffect for non-Compose callbacks
SideEffect {
analytics.setUserId(userId)
}
}
Output: Network call runs once per key. Listener cleaned up on disposal.
Prevention
- Always provide stable keys to
LaunchedEffectandDisposableEffect. - Use
LaunchedEffectfor async work,DisposableEffectfor cleanup. - Use
SideEffectfor non-Compose code that must run on every recomposition. - Never put suspend functions directly in a composable body.
Common Mistakes with compose effect
- Using
foldlinstead offoldl'causing stack overflow on large lists - Forgetting
deriving (Show, Eq)on custom data types needed for debugging - Placing the wildcard pattern first in case expressions, making all subsequent patterns unreachable
These mistakes appear frequently in real-world Android code. DodaTech's contributors have identified these patterns through analysis of open-source projects and production systems.
Practice Exercise
Write a pure function that safely divides two integers using Maybe, then test it with edge cases like division by zero and negative numbers.
This exercise reinforces the concepts covered in this guide. Try implementing it before checking online solutions.
FAQ
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro