Android Academy · Lektion

Platzhalter und Fehlerzustände

Lade- und Fehlerzustände elegant behandeln

Lektion 2 von 413 Schritte

Platzhalter und Fehlerzustände ist eine kostenlose Android Academy-Lektion auf CoddyKit. Dies ist Lektion 2 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des Android Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der Android Academy-Kurs umfasst insgesamt 4 Lektionen.

Laden geschieht nicht sofort

Bilder aus dem Netzwerk benötigen Zeit. Währenddessen zeigt Ihre UI … nichts, sofern Sie diesen Zustand nicht behandeln. Und manchmal kommt das Bild nie an: Die URL ist fehlerhaft, der Server nicht erreichbar oder der Benutzer offline.

Eine ausgereifte App zeigt während des Ladens einen Platzhalter und bei einem Fehler ein Ersatzbild, statt eine leere Fläche oder einen Absturz zu erzeugen. Coil macht beides einfach.

In dieser Lektion fügen Sie Platzhalter, Fehlerbilder und eine eigene UI für die einzelnen Zustände hinzu.

Ein einfacher Platzhalter

Am schnellsten fügen Sie einen Platzhalter hinzu, indem Sie über den Parameter placeholder von AsyncImage ein Drawable mit painterResource übergeben. Coil zeigt es an, bis das eigentliche Bild vollständig geladen ist.

Verwenden Sie ein neutrales, leichtgewichtiges Drawable, etwa ein graues Feld oder die Silhouette eines Logos.

import androidx.compose.runtime.Composable
import androidx.compose.ui.res.painterResource
import coil3.compose.AsyncImage

@Composable
fun ImageWithPlaceholder(url: String) {
    AsyncImage(
        model = url,
        contentDescription = null,
        placeholder = painterResource(R.drawable.placeholder_gray)
    )
}

Ein Fehlerbild hinzufügen

Der Parameter error zeigt ein Ersatz-Drawable an, wenn die Anfrage fehlschlägt. Außerdem gibt es fallback, das speziell verwendet wird, wenn das model den Wert null hat, also überhaupt keine zu ladenden Daten vorhanden sind.

Wenn Sie alle drei Optionen festlegen – placeholder, error und fallback –, decken Sie nahezu ohne zusätzlichen Code jeden visuellen Zustand ab.

import androidx.compose.runtime.Composable
import androidx.compose.ui.res.painterResource
import coil3.compose.AsyncImage

@Composable
fun RobustImage(url: String?) {
    AsyncImage(
        model = url,
        contentDescription = null,
        placeholder = painterResource(R.drawable.placeholder_gray),
        error = painterResource(R.drawable.image_broken),
        fallback = painterResource(R.drawable.no_image)
    )
}

Platzhalter über ImageRequest

Sie können diese Zustände auch direkt in der ImageRequest festlegen. Das ist praktisch, wenn Sie die Anfrage einmal erstellen und wiederverwenden oder gleichzeitig weitere Anfrageoptionen benötigen.

Die Funktionen auf Anfrageebene erwarten IDs von Drawable-Ressourcen.

import android.content.Context
import coil3.request.ImageRequest
import coil3.request.crossfade
import coil3.request.error
import coil3.request.placeholder

fun buildRequest(context: Context, url: String) =
    ImageRequest.Builder(context)
        .data(url)
        .crossfade(true)
        .placeholder(R.drawable.placeholder_gray)
        .error(R.drawable.image_broken)
        .build()

Eigene UI mit SubcomposeAsyncImage

Drawables sind oft ausreichend, aber manchmal benötigen Sie pro Zustand einen Spinner, einen Schimmer oder Text. Mit SubcomposeAsyncImage können Sie für loading, error und success echte Composables bereitstellen.

Diese Lösung ist flexibler, aber etwas aufwendiger. Bevorzugen Sie daher in langen Listen Drawable-Platzhalter und verwenden Sie Subcompose für besonders hervorgehobene Bilder.

import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import coil3.compose.SubcomposeAsyncImage

@Composable
fun HeroImage(url: String) {
    SubcomposeAsyncImage(
        model = url,
        contentDescription = "Hero",
        loading = { CircularProgressIndicator() },
        error = { Text("Could not load image") }
    )
}

Den Status direkt auslesen

Für vollständige Kontrolle verwenden Sie die API rememberAsyncImagePainter und untersuchen deren state. Der Status ist ein versiegelter Typ mit den Fällen Loading, Success, Error und Empty.

Damit können Sie Ihr eigenes Layout, Animationen oder Analysen abhängig vom eingetretenen Zustand steuern.

import androidx.compose.foundation.Image
import androidx.compose.runtime.Composable
import coil3.compose.AsyncImagePainter
import coil3.compose.rememberAsyncImagePainter

@Composable
fun StateAwareImage(url: String) {
    val painter = rememberAsyncImagePainter(model = url)
    val state = painter.state.collectAsState().value

    when (state) {
        is AsyncImagePainter.State.Loading -> { /* show spinner */ }
        is AsyncImagePainter.State.Error -> { /* show error UI */ }
        else -> Image(painter = painter, contentDescription = null)
    }
}

Einen Schimmer-Platzhalter anzeigen

Ein beliebtes Muster ist ein Schimmer: ein animierter grauer Farbverlauf, der andeutet, dass Inhalte geladen werden. Eine einfache Variante können Sie mit einem einfarbigen Feld hinter dem Ladezustand erstellen.

Hier verwenden wir SubcomposeAsyncImage mit einem eingefärbten Feld während des Ladens. Ersetzen Sie das Feld durch eine Schimmer-Bibliothek, wenn Sie den animierten Effekt wünschen.

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import coil3.compose.SubcomposeAsyncImage

@Composable
fun ShimmerImage(url: String) {
    SubcomposeAsyncImage(
        model = url,
        contentDescription = null,
        loading = {
            androidx.compose.foundation.layout.Box(
                Modifier.fillMaxSize()
                    .background(MaterialTheme.colorScheme.surfaceVariant)
            )
        }
    )
}

Mit einem null- oder leeren Model umgehen

Was ist, wenn Sie noch keine URL haben, etwa bei einem Benutzer ohne Profilbild? Wenn Sie null als Model übergeben, wird das fallback-Drawable ausgelöst – oder error, falls kein Fallback festgelegt ist.

So müssen Sie null nicht in Ihrem eigenen Code gesondert behandeln. Lassen Sie Coil einen Standardavatar anzeigen.

import androidx.compose.runtime.Composable
import androidx.compose.ui.res.painterResource
import coil3.compose.AsyncImage

@Composable
fun ProfilePicture(photoUrl: String?) {
    // If photoUrl is null, Coil shows the fallback default avatar.
    AsyncImage(
        model = photoUrl,
        contentDescription = "Profile picture",
        fallback = painterResource(R.drawable.default_avatar),
        error = painterResource(R.drawable.default_avatar)
    )
}

Fehler mit einem Listener erfassen

Manchmal müssen Sie im Code reagieren, wenn das Laden fehlschlägt, etwa um den Fehler zu protokollieren oder einen erneuten Versuch zu starten. ImageRequest.Builder akzeptiert einen listener mit Erfolgs- und Fehler-Callbacks.

Halten Sie diese Callbacks kurz, da sie im Hauptthread ausgeführt werden.

import android.content.Context
import android.util.Log
import coil3.request.ImageRequest

fun loggedRequest(context: Context, url: String) =
    ImageRequest.Builder(context)
        .data(url)
        .listener(
            onError = { _, result ->
                Log.e("Coil", "Load failed", result.throwable)
            },
            onSuccess = { _, _ ->
                Log.d("Coil", "Loaded $url")
            }
        )
        .build()

Farbton und Farbfilter

Platzhalter- und Fehler-Drawables wirken oft am besten, wenn sie an Ihr Theme angepasst eingefärbt werden. Sie können einen ColorFilter auf ein AsyncImage anwenden. Das eignet sich besonders für einfarbige, symbolartige Ersatzbilder, die sich an den hellen und dunklen Modus anpassen sollen.

Wenden Sie den Filter nur auf den gewünschten Platzhalter- oder Fehlerzustand an. Bei echten Fotos lassen Sie ihn normalerweise deaktiviert.

import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.res.painterResource
import coil3.compose.AsyncImage

@Composable
fun TintedFallback(url: String?) {
    AsyncImage(
        model = url,
        contentDescription = null,
        error = painterResource(R.drawable.ic_image_placeholder),
        colorFilter = ColorFilter.tint(MaterialTheme.colorScheme.onSurfaceVariant)
    )
}

Eine robuste Bildkomponente

Stellen wir nun eine wiederverwendbare Komponente zusammen, die jeden Zustand sauber behandelt: einen Hintergrund während des Ladens, ein Fehlerbild, Crossfade und Zuschneiden. Fügen Sie sie in eine Liste ein und machen Sie sich keine Gedanken mehr über leere Flächen.

import androidx.compose.foundation.layout.size
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp
import coil3.compose.AsyncImage
import coil3.request.ImageRequest
import coil3.request.crossfade

@Composable
fun ResilientImage(url: String?, size: Int = 96) {
    val context = LocalContext.current
    AsyncImage(
        model = ImageRequest.Builder(context)
            .data(url)
            .crossfade(true)
            .build(),
        contentDescription = null,
        contentScale = ContentScale.Crop,
        placeholder = painterResource(R.drawable.placeholder_gray),
        error = painterResource(R.drawable.image_broken),
        fallback = painterResource(R.drawable.default_avatar),
        modifier = Modifier.size(size.dp)
    )
}

Schnelltest

Sie übergeben model = null an AsyncImage. Welches Drawable zeigt Coil standardmäßig an?

Zusammenfassung

Sie haben das Laden von Bildern robust gestaltet. Die wichtigsten Punkte:

  • placeholder wird während des Ladens angezeigt, error bei einem Fehler und fallback, wenn das Model null ist.
  • Sie können diese auf AsyncImage oder auf der ImageRequest festlegen.
  • Mit SubcomposeAsyncImage können Sie für jeden Zustand echte Composables (Spinner, Shimmer) bereitstellen.
  • rememberAsyncImagePainter stellt den unverarbeiteten state für vollständige Kontrolle bereit.
  • Verwenden Sie einen listener der Anfrage, um Ladeergebnisse zu protokollieren oder darauf zu reagieren.

Als Nächstes: Caching und Performance, damit Bilder beim zweiten Mal sofort geladen werden.

Kostenlos starten

Lerne Kotlin mit einem KI-Tutor — kostenlos

Schreibe und führe echten Code in deinem Browser aus, bekomme sofortige Hilfe von einem 24/7 KI-Tutor und setze dein Lernen im Web oder in der App fort.

Kurse
36
Lektionen
152

Häufig gestellte Fragen

Ist die Lektion „Platzhalter und Fehlerzustände“ kostenlos?

Ja — der vollständige Text von „Platzhalter und Fehlerzustände“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des Android Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der Android Academy-Kurs umfasst insgesamt 4 Lektionen.

Was lerne ich in „Platzhalter und Fehlerzustände“?

Lade- und Fehlerzustände elegant behandeln Du übst Android Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.

Brauche ich Erfahrung, um Android Academy zu starten?

Keine Vorkenntnisse erforderlich. Android Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 2 von 4.

Wie lange dauert die Lektion „Platzhalter und Fehlerzustände“?

Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.

Kann ich in dieser Android Academy-Lektion Code schreiben und ausführen?

Ja. Jede Android Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.

Alle Lektionen in diesem Kurs

  1. Bilder mit Coil laden
  2. Platzhalter und Fehlerzustände
  3. Caching und Performance
  4. Audio und Video abspielen
← Zurück zu Android Academy