Android Academy · Lektion

Caching og ydeevne

Grundlæggende caching i hukommelse og på disk.

Lektion 3 af 413 trin

Caching og ydeevne er en gratis Android Academy-lektion på CoddyKit. Dette er lektion 3 af 4. Du kan læse alle 3 lektioner i dette læringsspor gratis i deres fulde længde — derefter låser CoddyKit PRO alle lektioner op samt praktiske øvelser med en indbygget kodeeditor og en AI-underviser døgnet rundt. Den er en del af læringsforløbet i Android Academy, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. Android Academy-kurset indeholder 4 lektioner i alt.

Hvorfor caching er vigtigt

Det er ressourcekrævende at downloade og afkode et billede: Det bruger båndbredde, batteri og CPU. Hvis du henter det samme billede igen, hver gang en liste rulles, føles appen langsom og bruger unødvendigt meget data.

Caching gemmer afkodede billeder og downloadede bytes, så den næste forespørgsel næsten sker øjeblikkeligt. Coil leveres som standard med to caches: en cache i hukommelsen (hurtige, afkodede bitmaps) og en diskcache (vedvarende, rå bytes).

Denne lektion forklarer, hvordan de fungerer, og hvordan du finjusterer dem.

To lag: hukommelse og disk

Coil tjekker caches i denne rækkefølge:

  • Hukommelsescache: indeholder nyligt brugte, afkodede bitmaps i RAM. Et hit her er øjeblikkeligt, fordi afkodning ikke er nødvendig.
  • Diskcache: gemmer de oprindeligt downloadede bytes på enheden. Et hit her springer netværket over, men billedet skal stadig afkodes.
  • Netværk: den langsomme vej, som kun bruges, når der ikke er et hit i nogen af cacherne.

Hukommelsen er hurtig, men begrænset og ryddes, når appen lukkes; disken har mere plads og overlever genstarter.

Konfiguration af ImageLoader

Caches hører til på ImageLoader, som er motoren bag alle forespørgsler. Du opretter normalt én tilpasset loader og genbruger den. Her indstiller vi hukommelsescachen til en procentdel af den tilgængelige RAM og diskcachen til en fast grænse i bytes.

En singleton-loader forhindrer dublerede caches og spild af hukommelse.

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()

Levering af en singleton-loader

Coil 3 lader dig angive én loader for hele applikationen ved at implementere SingletonImageLoader.Factory på din Application-klasse. Derefter bruger alle AsyncImage-forekomster den automatisk, så du ikke behøver at angive en loader hver gang.

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()
}

Styring af cachepolitikker

Hver forespørgsel kan vælge caching til eller fra med memoryCachePolicy og diskCachePolicy. Politikkerne er ENABLED, READ_ONLY, WRITE_ONLY eller DISABLED.

Du kan for eksempel deaktivere hukommelsescachen for meget store billeder, der kun bruges én gang, og som du ikke vil beholde i RAM, eller deaktivere disken for følsomt indhold.

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()

Tilpas størrelsen: Afkod ikke enorme bitmaps

Den største enkeltstående fejl, når det gælder ydeevne, er at afkode et foto på 4000x3000 som en miniature på 100dp. Det spilder både hukommelse og tid. Som standard tilpasser Coil bitmapstørrelsen til composablens målte grænser, så en lille AsyncImage afkoder et lille bitmap.

Du kan gennemtvinge en bestemt målestørrelse med size() på forespørgslen, når du kender dimensionerne.

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-nøgler

Coil udleder en cache-nøgle fra dataene i forespørgslen. Hvis dine URL'er indeholder parametre, der ændrer sig (for eksempel et signeret token), får identiske billeder forskellige nøgler og rammer aldrig cachen.

Angiv eksplicit memoryCacheKey og diskCacheKey baseret på den stabile del, for eksempel billedets id, så caching fungerer.

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()

Forudindlæsning af billeder

Du kan gøre oplevelsen mere flydende ved at varme cachen op, før et billede vises, for eksempel ved at hente den næste side i et feed på forhånd. Brug loaderens enqueue med en forespørgsel uden et mål.

Når brugeren når frem til billedet, ligger det allerede i cachen og vises øjeblikkeligt.

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)
    }
}

Rydning af cachen

Af og til har du brug for at frigøre plads eller tvinge en opdatering igennem, for eksempel efter at brugeren har opdateret sit profilbillede. Du kan rydde hukommelsescachen, diskcachen eller fjerne en enkelt nøgle.

Det er omfattende at rydde alt, så foretræk at fjerne bestemte nøgler, når du kan.

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 kontra cache-hits

Crossfade ser flot ud ved indlæsning over netværket, men kan føles langsom, når et billede kommer direkte fra hukommelsescachen og kunne vises øjeblikkeligt. Coil håndterer dette intelligent: Som standard springer den crossfade-animationen over ved hits i hukommelsescachen og animerer kun billeder, der rent faktisk er blevet indlæst.

Du får derfor jævne overtoninger ved den første indlæsning og øjeblikkelig visning, når du ruller gennem cachelagrede billeder, uden at du behøver gøre noget ekstra.

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()

Tjekliste til ydeevne i lister

Når du viser mange billeder i en LazyColumn eller et gitter, skal du følge disse regler for jævn rulning:

  • Giv hvert billede en fast størrelse, så Coil afkoder et lille bitmap.
  • Genbrug én singleton-ImageLoader, så caches deles.
  • Brug ContentScale.Crop for at undgå forskydninger i layoutet.
  • Sørg for, at cache-nøglerne er stabile på tværs af genindlæsninger.
  • Lad Coil automatisk annullere forespørgsler uden for skærmen, og modarbejd ikke dette.
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)
            )
        }
    }
}

Hurtigt tjek

Coil tjekker sine caches, før den bruger netværket. Hvilken cache er hurtigst, når der er et hit, fordi den helt springer afkodningen over?

Opsummering

Du har lært, hvordan Coil holder billeder hurtige:

  • To caches: hukommelse (afkodet, hurtig, lille) og disk (rå bytes, vedvarende, større).
  • Konfigurer størrelser på en tilpasset ImageLoader, og eksponér én via SingletonImageLoader.Factory.
  • Finjuster adfærden for hver forespørgsel med memoryCachePolicy og diskCachePolicy.
  • Afkod altid i visningsstørrelsen, og angiv size() eksplicit, når det er nødvendigt.
  • Brug stabile cache-nøgler, forudindlæs kommende billeder, og ryd bestemte nøgler for at tvinge en opdatering.

Næste emne er at gå videre fra billeder til afspilning af lyd og video.

Gratis at komme i gang

Lær Kotlin med en AI-underviser — gratis

Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.

Kurser
36
Lektioner
152

Ofte stillede spørgsmål

Er lektionen “Caching og ydeevne” gratis?

Ja — alle 3 lektioner i læringssporet Android Academy, inklusive “Caching og ydeevne”, kan læses gratis i deres fulde længde her på webstedet. Derefter låser CoddyKit PRO alle lektioner op samt interaktive øvelser med en indbygget kodeeditor og en AI-underviser døgnet rundt. Android Academy-kurset indeholder 4 lektioner i alt.

Hvad lærer jeg i “Caching og ydeevne”?

Grundlæggende caching i hukommelse og på disk. Du øver dig i Android Academy med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.

Skal jeg have erfaring for at begynde på Android Academy?

Der kræves ingen tidligere erfaring. Android Academy på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 3 af 4.

Hvor lang tid tager lektionen “Caching og ydeevne”?

De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.

Kan jeg skrive og køre kode i denne Android Academy-lektion?

Ja. Alle Android Academy-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.

Alle lektioner i dette kursus

  1. Indlæsning af billeder med Coil
  2. Pladsholdere og fejltilstande
  3. Caching og ydeevne
  4. Afspilning af lyd og video
← Tilbage til Android Academy