Caching und Performance
Grundlagen des Speicher- und Festplatten-Cachings
Caching und Performance ist eine kostenlose Android Academy-Lektion auf CoddyKit. Dies ist Lektion 3 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.
Warum Caching wichtig ist
Das Herunterladen und Dekodieren eines Bildes ist aufwendig: Es verbraucht Bandbreite, Akku und CPU. Wenn Sie dasselbe Bild bei jedem Scrollen einer Liste erneut laden, wirkt Ihre App langsam und verbraucht unnötig Datenvolumen.
Caching speichert dekodierte Bilder und heruntergeladene Bytes, sodass die nächste Anfrage nahezu sofort beantwortet wird. Coil verfügt standardmäßig über zwei Caches: einen Memory-Cache (schnell, dekodierte Bitmaps) und einen Disk-Cache (persistent, ursprüngliche Bytes).
In dieser Lektion erfahren Sie, wie sie funktionieren und wie Sie sie abstimmen.
Zwei Ebenen: Memory und Disk
Coil prüft die Caches in dieser Reihenfolge:
- Memory-Cache: Enthält zuletzt verwendete, dekodierte Bitmaps im RAM. Ein Treffer wird sofort geliefert, eine Dekodierung ist nicht erforderlich.
- Disk-Cache: Speichert die ursprünglich heruntergeladenen Bytes auf dem Gerät. Ein Treffer überspringt das Netzwerk, muss aber weiterhin dekodiert werden.
- Netzwerk: Der langsame Weg, der nur verwendet wird, wenn beide Caches keinen Treffer liefern.
Der Memory-Cache ist schnell, aber klein und wird beim Beenden der App geleert. Der Disk-Cache ist größer und bleibt über Neustarts hinweg erhalten.
Den ImageLoader konfigurieren
Die Caches befinden sich im ImageLoader, der Engine hinter jeder Anfrage. Üblicherweise erstellen Sie einen eigenen Loader und verwenden ihn wieder. Hier dimensionieren wir den Memory-Cache als Prozentsatz des verfügbaren RAMs und den Disk-Cache mit einem festen Byte-Limit.
Ein Singleton-Loader verhindert doppelte Caches und verschwendeten Speicher.
import android.content.Context
import coil3.ImageLoader
import coil3.disk.DiskCache
import coil3.memory.MemoryCache
import okio.Path.Companion.toOkioPath
fun newImageLoader(context: Context): ImageLoader =
ImageLoader.Builder(context)
.memoryCache {
MemoryCache.Builder()
.maxSizePercent(context, 0.25) // 25% of app RAM
.build()
}
.diskCache {
DiskCache.Builder()
.directory(context.cacheDir.resolve("image_cache").toOkioPath())
.maxSizeBytes(50L * 1024 * 1024) // 50 MB
.build()
}
.build()Einen Singleton-Loader bereitstellen
Mit Coil 3 können Sie einen anwendungsweit gültigen Loader festlegen, indem Sie SingletonImageLoader.Factory in Ihrer Application-Klasse implementieren. Danach verwendet jedes AsyncImage ihn automatisch, ohne dass Sie jedes Mal einen Loader übergeben müssen.
import android.app.Application
import coil3.ImageLoader
import coil3.PlatformContext
import coil3.SingletonImageLoader
class MyApp : Application(), SingletonImageLoader.Factory {
override fun newImageLoader(context: PlatformContext): ImageLoader =
ImageLoader.Builder(context)
.crossfade(true)
.build()
}Cache-Richtlinien steuern
Jede Anfrage kann das Caching mit memoryCachePolicy und diskCachePolicy aktivieren oder deaktivieren. Die Richtlinien sind ENABLED, READ_ONLY, WRITE_ONLY oder DISABLED.
Deaktivieren Sie beispielsweise den Memory-Cache für sehr große, einmalig verwendete Bilder, die Sie nicht im RAM behalten möchten, oder den Disk-Cache für sensible Inhalte.
import android.content.Context
import coil3.request.CachePolicy
import coil3.request.ImageRequest
fun noMemoryCacheRequest(context: Context, url: String) =
ImageRequest.Builder(context)
.data(url)
.memoryCachePolicy(CachePolicy.DISABLED)
.diskCachePolicy(CachePolicy.ENABLED)
.build()Größe anpassen: Keine riesigen Bitmaps dekodieren
Der größte Performancefehler besteht darin, ein Foto mit 4000x3000 Pixeln in eine 100dp große Miniaturansicht zu dekodieren. Das verschwendet Speicher und Zeit. Standardmäßig passt Coil die Größe der Bitmap an die gemessenen Abmessungen des Composables an, sodass ein kleines AsyncImage eine kleine Bitmap dekodiert.
Wenn Sie die Abmessungen kennen, können Sie mit size() in der Anfrage eine explizite Zielgröße erzwingen.
import android.content.Context
import coil3.request.ImageRequest
import coil3.size.Size
fun thumbnailRequest(context: Context, url: String) =
ImageRequest.Builder(context)
.data(url)
.size(Size(200, 200)) // decode at most 200x200
.build()Stabile Cache-Schlüssel
Coil leitet den Cache-Schlüssel aus den Anfragedaten ab. Wenn Ihre URLs veränderliche Query-Parameter enthalten (etwa ein signiertes Token), erhalten identische Bilder unterschiedliche Schlüssel und werden nie aus dem Cache geladen.
Setzen Sie memoryCacheKey und diskCacheKey explizit anhand des stabilen Bestandteils (z. B. der Bild-ID), damit das Caching funktioniert.
import android.content.Context
import coil3.request.ImageRequest
fun stableKeyRequest(context: Context, id: String, signedUrl: String) =
ImageRequest.Builder(context)
.data(signedUrl)
.memoryCacheKey("image_$id")
.diskCacheKey("image_$id")
.build()Bilder vorab laden
Für eine flüssigere Nutzererfahrung können Sie den Cache aufwärmen, bevor ein Bild angezeigt wird, etwa indem Sie die nächste Seite eines Feeds vorab laden. Verwenden Sie dafür enqueue des Loaders mit einer Anfrage ohne Target.
Wenn der Benutzer das Bild erreicht, befindet es sich bereits im Cache und wird sofort angezeigt.
import android.content.Context
import coil3.ImageLoader
import coil3.request.ImageRequest
fun preload(context: Context, loader: ImageLoader, urls: List<String>) {
urls.forEach { url ->
val request = ImageRequest.Builder(context)
.data(url)
.build()
loader.enqueue(request)
}
}Den Cache leeren
Gelegentlich müssen Sie Speicherplatz freigeben oder eine Aktualisierung erzwingen, etwa nachdem der Benutzer sein Profilbild geändert hat. Sie können den Memory-Cache, den Disk-Cache oder einen einzelnen Schlüssel löschen.
Alles zu löschen ist aufwendig. Entfernen Sie möglichst bestimmte Schlüssel.
import coil3.ImageLoader
import coil3.memory.MemoryCache
fun refreshAvatar(loader: ImageLoader, key: String) {
// Remove one entry so the next load refetches
loader.memoryCache?.remove(MemoryCache.Key(key))
loader.diskCache?.remove(key)
}
fun clearAll(loader: ImageLoader) {
loader.memoryCache?.clear()
// Disk clearing is heavier; do it sparingly
}Crossfade und Cache-Treffer
Crossfade sieht beim Laden aus dem Netzwerk großartig aus, kann aber träge wirken, wenn ein Bild direkt aus dem Memory-Cache kommt und sofort angezeigt werden könnte. Coil berücksichtigt dies automatisch: Standardmäßig überspringt es die Crossfade-Animation bei Treffern im Memory-Cache und animiert nur tatsächlich geladene Bilder.
So erhalten Sie sanfte Überblendungen beim ersten Laden und eine sofortige Anzeige beim Scrollen zu bereits zwischengespeicherten Bildern – ganz ohne zusätzlichen Aufwand.
import android.content.Context
import coil3.request.ImageRequest
import coil3.request.crossfade
fun feedRequest(context: Context, url: String) =
ImageRequest.Builder(context)
.data(url)
// Crossfade plays on real loads; memory-cache hits show instantly
.crossfade(true)
.build()Performance-Checkliste für Listen
Beachten Sie beim Anzeigen vieler Bilder in einer LazyColumn oder einem Raster die folgenden Regeln für flüssiges Scrollen:
- Geben Sie jedem Bild eine feste Größe, damit Coil eine kleine Bitmap dekodiert.
- Verwenden Sie einen einzigen Singleton-
ImageLoader, damit die Caches gemeinsam genutzt werden. - Verwenden Sie
ContentScale.Crop, um Verschiebungen im Layout zu vermeiden. - Halten Sie die Cache-Schlüssel über mehrere Ladevorgänge hinweg stabil.
- Lassen Sie Coil Anfragen außerhalb des sichtbaren Bereichs automatisch abbrechen, statt dagegen anzukämpfen.
import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.foundation.lazy.grid.items
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.ContentScale
import coil3.compose.AsyncImage
@Composable
fun PhotoGrid(urls: List<String>) {
LazyVerticalGrid(columns = GridCells.Fixed(3)) {
items(urls) { url ->
AsyncImage(
model = url,
contentDescription = null,
contentScale = ContentScale.Crop,
modifier = Modifier.aspectRatio(1f)
)
}
}
}Schnelltest
Coil prüft seine Caches, bevor es auf das Netzwerk zugreift. Welcher Cache ist bei einem Treffer am schnellsten, weil er die Dekodierung vollständig überspringt?
Zusammenfassung
Sie haben gelernt, wie Coil Bilder schnell hält:
- Zwei Caches: Memory (dekodiert, schnell, klein) und Disk (ursprüngliche Bytes, persistent, größer).
- Konfigurieren Sie die Größen in einem benutzerdefinierten
ImageLoaderund stellen Sie einen überSingletonImageLoader.Factorybereit. - Passen Sie das Verhalten pro Anfrage mit
memoryCachePolicyunddiskCachePolicyan. - Dekodieren Sie immer in der Anzeigegröße. Setzen Sie bei Bedarf explizit
size(). - Verwenden Sie stabile Cache-Schlüssel, laden Sie bevorstehende Bilder vorab und löschen Sie bestimmte Schlüssel, um eine Aktualisierung zu erzwingen.
Als Nächstes: Über Bilder hinausgehen und Audio und Video abspielen.
Häufig gestellte Fragen
Ist die Lektion „Caching und Performance“ kostenlos?
Ja — der vollständige Text von „Caching und Performance“ 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 „Caching und Performance“?
Grundlagen des Speicher- und Festplatten-Cachings 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 3 von 4.
Wie lange dauert die Lektion „Caching und Performance“?
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
- Bilder mit Coil laden
- Platzhalter und Fehlerzustände
- Caching und Performance
- Audio und Video abspielen