Mise en cache et performances
Principes de la mise en cache en mémoire et sur disque.
Mise en cache et performances est une leçon Android Academy gratuite sur CoddyKit. Ceci est la leçon 3 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage Android Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours Android Academy comprend 4 leçons au total.
Pourquoi la mise en cache est importante
Télécharger et décoder une image coûte cher : cela utilise de la bande passante, de la batterie et du CPU. Si vous récupérez à nouveau la même image à chaque défilement d'une liste, votre application semble lente et consomme beaucoup de données.
La mise en cache stocke les images décodées et les octets téléchargés afin que la requête suivante soit presque instantanée. Coil fournit par défaut deux caches : un cache en mémoire (rapide, images décodées) et un cache sur disque (persistant, octets bruts).
Cette leçon explique leur fonctionnement et la manière de les régler.
Deux couches : mémoire et disque
Coil vérifie les caches dans cet ordre :
- Cache en mémoire : contient les images bitmap décodées récemment utilisées dans la RAM. Une correspondance est instantanée : aucun décodage n'est nécessaire.
- Cache sur disque : stocke les octets originaux téléchargés sur l'appareil. Une correspondance évite le réseau, mais nécessite toujours un décodage.
- Réseau : le chemin le plus lent, utilisé uniquement lorsque les deux caches ne contiennent pas l'image.
La mémoire est rapide, mais limitée, et elle est vidée lorsque l'application s'arrête ; le disque est plus grand et persiste après les redémarrages.
Configurer l'ImageLoader
Les caches résident dans ImageLoader, le moteur qui se trouve derrière chaque requête. En général, vous créez un chargeur personnalisé et le réutilisez. Ici, nous dimensionnons le cache en mémoire selon un pourcentage de la RAM disponible et le cache sur disque selon un budget fixe en octets.
Un chargeur unique évite les caches en double et le gaspillage de mémoire.
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()Fournir un chargeur unique
Coil 3 vous permet de définir un chargeur unique pour toute l'application en implémentant SingletonImageLoader.Factory sur votre classe Application. Ensuite, chaque AsyncImage l'utilise automatiquement : il n'est pas nécessaire de transmettre un chargeur à chaque fois.
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()
}Contrôler les stratégies de cache
Chaque requête peut activer ou désactiver la mise en cache avec memoryCachePolicy et diskCachePolicy. Les stratégies sont ENABLED, READ_ONLY, WRITE_ONLY ou DISABLED.
Par exemple, désactivez le cache en mémoire pour les images volumineuses utilisées une seule fois que vous ne souhaitez pas conserver dans la RAM, ou désactivez le cache sur disque pour les contenus sensibles.
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()Redimensionner : ne décodez pas d'images bitmap géantes
La plus grosse erreur de performance consiste à décoder une photo de 4000×3000 dans une miniature de 100dp. Cela gaspille de la mémoire et du temps. Par défaut, Coil adapte la taille de l'image bitmap aux dimensions mesurées du composable : un petit AsyncImage décode donc une petite image bitmap.
Vous pouvez imposer une taille cible précise avec size() sur la requête lorsque vous connaissez les dimensions.
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()Clés de cache stables
Coil dérive une clé de cache à partir des données de la requête. Si vos URL contiennent des paramètres de requête variables (comme un jeton signé), des images identiques obtiennent des clés différentes et ne sont jamais trouvées dans le cache.
Définissez explicitement memoryCacheKey et diskCacheKey à partir de la partie stable (par exemple l'identifiant de l'image) afin que la mise en cache fonctionne.
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()Précharger les images
Pour une expérience plus fluide, vous pouvez réchauffer le cache avant l'affichage d'une image, par exemple en préchargeant la page suivante d'un fil. Utilisez enqueue du chargeur avec une requête sans cible.
Lorsque l'utilisateur atteint l'image, celle-ci est déjà en cache et s'affiche instantanément.
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)
}
}Vider le cache
Vous devez parfois libérer de l'espace ou forcer une actualisation, par exemple après la modification de l'avatar de l'utilisateur. Vous pouvez vider le cache en mémoire, le cache sur disque ou supprimer une seule clé.
Tout vider est une opération lourde ; préférez supprimer des clés précises lorsque c'est possible.
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
}Fondu enchaîné ou correspondance dans le cache
Le fondu enchaîné est très agréable pour les chargements depuis le réseau, mais il peut sembler lent lorsqu'une image provient directement du cache en mémoire et pourrait s'afficher instantanément. Coil est prévoyant : par défaut, il ignore l'animation de fondu pour les correspondances du cache en mémoire et n'anime que les images réellement chargées.
Vous obtenez ainsi des fondus fluides lors du premier chargement et un affichage instantané pendant les défilements avec des images en cache, sans travail supplémentaire.
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()Liste de contrôle des performances pour les listes
Lorsque vous affichez de nombreuses images dans une LazyColumn ou une grille, suivez ces règles pour obtenir un défilement fluide :
- Donnez à chaque image une taille fixe afin que Coil décode une petite image bitmap.
- Réutilisez un unique
ImageLoaderpour partager les caches. - Utilisez
ContentScale.Croppour éviter les décalages de mise en page. - Conservez des clés de cache stables entre les rechargements.
- Laissez Coil annuler automatiquement les requêtes hors écran ; n'intervenez pas.
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)
)
}
}
}Vérification rapide
Coil vérifie ses caches avant d'utiliser le réseau. Quel cache, lorsqu'il contient l'image, est le plus rapide parce qu'il évite entièrement le décodage ?
Récapitulatif
Vous avez appris comment Coil accélère l'affichage des images :
- Deux caches : mémoire (décodée, rapide, limitée) et disque (octets bruts, persistant, plus grand).
- Configurez les tailles sur un
ImageLoaderpersonnalisé et rendez-en un seul disponible viaSingletonImageLoader.Factory. - Réglez le comportement de chaque requête avec
memoryCachePolicyetdiskCachePolicy. - Décodez toujours à la taille d'affichage ; définissez explicitement
size()lorsque nécessaire. - Utilisez des clés de cache stables, préchargez les images à venir et supprimez des clés précises pour actualiser le contenu.
Ensuite : dépasser le cadre des images pour lire de l'audio et de la vidéo.
Questions Fréquemment Posées
La leçon « Mise en cache et performances » est-elle gratuite ?
Oui — le texte complet de « Mise en cache et performances » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours Android Academy, passe à CoddyKit PRO. Le cours Android Academy comprend 4 leçons au total.
Qu'est-ce que j'apprendrai dans « Mise en cache et performances » ?
Principes de la mise en cache en mémoire et sur disque. Tu pratiques Android Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.
Dois-je avoir de l'expérience pour commencer Android Academy ?
Aucune expérience préalable n'est requise. Android Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 3 sur 4.
Combien de temps prend la leçon « Mise en cache et performances » ?
La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.
Peux-tu écrire et exécuter du code dans cette leçon Android Academy ?
Oui. Chaque leçon Android Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.
Toutes les leçons de ce cours
- Charger des images avec Coil
- Espaces réservés et états d’erreur
- Mise en cache et performances
- Lire des fichiers audio et vidéo