DisposableEffect in Compose – aufräumen, wenn ein Composable verschwindet
Immer wenn du in Compose etwas registrierst – einen Listener, einen Sensor, einen Callback – musst du es auch wieder abmelden. Genau dafür gibt es DisposableEffect mit seinem onDispose-Block.
LaunchedEffect kennst du vielleicht schon – der ist für Coroutinen beim Erscheinen eines Composables. Aber was, wenn du etwas registrierst, das du später wieder abmelden musst: einen BroadcastReceiver, einen Sensor-Listener, einen NetworkCallback? Meldest du ihn nicht ab, läuft er weiter, hält Referenzen fest und leakt Speicher. Genau dafür gibt es DisposableEffect – mit einem onDispose-Block, der garantiert aufräumt.
Registrieren und sauber wieder abmelden
Ein Beispiel, das den Online-Status des Geräts beobachtet:
@Composable
fun rememberIsOnline(): State<Boolean> {
val context = LocalContext.current
val isOnline = remember { mutableStateOf(true) }
DisposableEffect(context) {
val cm = context.getSystemService(ConnectivityManager::class.java)
val callback = object : ConnectivityManager.NetworkCallback() {
override fun onAvailable(network: Network) { isOnline.value = true }
override fun onLost(network: Network) { isOnline.value = false }
}
cm.registerDefaultNetworkCallback(callback) // anmelden
onDispose {
cm.unregisterNetworkCallback(callback) // WIEDER abmelden!
}
}
return isOnline
}Im UI nutzt du das dann ganz normal:
val online by rememberIsOnline()
if (!online) {
Text("Keine Verbindung", color = MaterialTheme.colorScheme.error)
}Was genau passiert – und wann
onDisposeläuft immer, wenn der Composable die Komposition verlässt (der Screen wird verlassen) oder bevor der Effekt wegen geänderter Keys neu startet. So bleibt kein Callback zurück.- Die Keys steuern den Neustart.
DisposableEffect(context)startet neu (erstonDispose, dann neu registrieren), sobald sichcontextändert. Brauchst du „genau einmal beim Erscheinen", nimm einen konstanten Key wieDisposableEffect(Unit). onDisposemuss die letzte Anweisung sein – der Compiler erzwingt das. Da hinein gehört ausschließlich das Aufräumen.
Die Faustregel: LaunchedEffect für Coroutinen-Arbeit (laden, beobachten), DisposableEffect immer dann, wenn es zu deiner Anmeldung ein passendes „Abmelden" gibt.
Du willst eine Android-App ohne Speicherlecks und mit sauberem Lebenszyklus? Ich helfe dir weiter.
Quellen
Du brauchst mehr als ein Snippet?
Ich entwickle Android-Apps in Kotlin und moderne Websites für Selbstständige und kleine Unternehmen — von der ersten Idee bis zum Release.
Projekt anfragen →Verwandte Snippets
collectAsStateWithLifecycle – Flows sammeln, ohne im Hintergrund zu verschwenden
collectAsState sammelt einen Flow auch, wenn die App im Hintergrund ist. collectAsStateWithLifecycle stoppt automatisch, sobald der Screen nicht mehr sichtbar ist – der richtige Standard für UI-State aus dem ViewModel.
Navigation in Compose – NavHost mit Argumenten
Von der Liste zum Detail und mit einer ID zurück: Navigation Compose macht das mit NavHost, Routen und typisierten Argumenten. So richtest du den Grundfluss sauber ein.
Einstellungen speichern mit DataStore – der moderne Ersatz für SharedPreferences
SharedPreferences ist alt, blockiert den Main-Thread und kennt keine Coroutinen. DataStore macht dasselbe – nur asynchron, typsicher und als Flow. So speicherst du Nutzer-Einstellungen richtig.