withContext(Dispatchers.IO) – schwere Arbeit vom Main-Thread nehmen
Datei lesen oder ein Bild dekodieren blockiert den Main-Thread und ruckelt die UI. Mit withContext(Dispatchers.IO) schiebst du blockierende Arbeit sauber auf einen Hintergrund-Thread.
Auf Android läuft die UI auf dem Main-Thread. Alles, was dort blockiert – eine Datei lesen, ein Bild dekodieren, eine langsame Berechnung – lässt die Oberfläche ruckeln oder friert sie im schlimmsten Fall ein (ANR). Die saubere Lösung mit Coroutines: withContext(Dispatchers.IO) schiebt genau diesen Teil auf einen Hintergrund-Thread und gibt das Ergebnis zurück.
Blockierende Arbeit auslagern
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
class ThumbnailRepository(private val api: ApiService) {
// suspend-Funktion: der Aufrufer bleibt "main-safe",
// die blockierende Arbeit passiert auf einem IO-Thread.
suspend fun loadThumbnail(url: String): Bitmap = withContext(Dispatchers.IO) {
val bytes = api.download(url) // blockierend (Netzwerk/Datei)
BitmapFactory.decodeByteArray(bytes, 0, bytes.size) // blockierend (CPU/IO)
}
}Der Aufruf aus dem ViewModel bleibt schlank und main-sicher:
viewModelScope.launch {
val bitmap = repo.loadThumbnail(url) // wartet, ohne den Main-Thread zu blockieren
_thumbnail.value = bitmap
}Welchen Dispatcher wofür?
Dispatchers.IO– Netzwerk, Datei-/Datenbankzugriff, alles, was auf Ein-/Ausgabe wartet.Dispatchers.Default– reine CPU-Arbeit (Sortieren, Parsen großer Listen, Bildfilter).Dispatchers.Main– UI-Updates; hier landet der Code nachwithContextautomatisch wieder.
Zwei Dinge, die du dir merken solltest
withContextgibt einen Wert zurück – anders alslaunch. Das Ergebnis der letzten Zeile ist der Rückgabewert.- Retrofit und Room sind schon main-safe. Deren
suspend-Funktionen wechseln intern selbst den Thread – die musst du *nicht* zusätzlich inwithContext(Dispatchers.IO)wickeln. Der Wrapper ist für *deinen* eigenen blockierenden Code.
Wenn du eine flüssige Android-App in Kotlin & Compose brauchst – ohne Ruckler und ANRs – sprich mich an.
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
Google Gemini in einer Android-App (Kotlin, über dein eigenes Backend)
Ein KI-Feature in eine Kotlin-App bringen – mit Google Gemini. Warum der API-Key nie in die App gehört, wie der generateContent-Aufruf aussieht und wie du ihn sauber aus einer Coroutine startest.
derivedStateOf – abgeleiteten Zustand berechnen, ohne Recompositions zu verschwenden
Wenn du aus einem sich schnell ändernden State einen selten wechselnden Wert ableitest (z. B. "Nach-oben-Button ab Item 5"), verhindert derivedStateOf, dass dein UI bei jedem Scroll-Pixel neu zeichnet.
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.