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
Parallele Netzwerkaufrufe mit async/await – zwei Requests, halbe Wartezeit
Wenn ein Screen zwei unabhängige Daten braucht, musst du nicht erst auf den einen und dann auf den anderen Request warten. Mit async und coroutineScope laufen sie parallel – strukturiert und sicher.
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.
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.