Perché il caching delle immagini è importante
In molte app Flutter le immagini provengono da URL remoti: avatar, copertine, gallerie di prodotti. Caricare ogni volta queste immagini dalla rete è costoso in termini di banda, batteria e tempi di attesa. Senza una cache adeguata, scorrere una lista comporta richieste HTTP ripetute e fastidiosi sfarfallii.
Il widget Image.network di Flutter offre una cache solo in memoria, che viene svuotata alla chiusura dell'app e quando la pressione di memoria aumenta. Per una soluzione robusta, con cache anche su disco, la libreria di riferimento è cached_network_image.
Installazione
Aggiungi la dipendenza al tuo pubspec.yaml:
dependencies:
cached_network_image: ^3.4.1
Poi esegui flutter pub get.
Utilizzo di base
Nel caso più semplice basta sostituire Image.network con CachedNetworkImage:
import 'package:cached_network_image/cached_network_image.dart';
CachedNetworkImage(
imageUrl: 'https://example.com/foto.jpg',
placeholder: (context, url) => const CircularProgressIndicator(),
errorWidget: (context, url, error) => const Icon(Icons.error),
)
La prima volta l'immagine viene scaricata e salvata su disco; le volte successive viene letta direttamente dalla cache locale, in modo quasi istantaneo.
Placeholder e gestione degli errori
Uno dei vantaggi principali è la possibilità di mostrare contenuti diversi durante il caricamento e in caso di errore. Per migliorare la UX si può usare un effetto shimmer o un'immagine di fallback:
CachedNetworkImage(
imageUrl: imageUrl,
fadeInDuration: const Duration(milliseconds: 300),
placeholder: (context, url) => Container(
color: Colors.grey.shade300,
),
errorWidget: (context, url, error) => Image.asset(
'assets/placeholder.png',
fit: BoxFit.cover,
),
fit: BoxFit.cover,
)
Il parametro fadeInDuration permette una transizione morbida quando l'immagine appare, evitando l'effetto "a scatto".
Usare l'immagine come provider
A volte serve un ImageProvider invece di un widget, ad esempio per un CircleAvatar o un DecorationImage. In questo caso si usa CachedNetworkImageProvider:
CircleAvatar(
radius: 24,
backgroundImage: CachedNetworkImageProvider(avatarUrl),
)
Container(
decoration: BoxDecoration(
image: DecorationImage(
image: CachedNetworkImageProvider(coverUrl),
fit: BoxFit.cover,
),
),
)
Ridimensionamento e memoria
Un errore comune è caricare immagini ad alta risoluzione in spazi piccoli, sprecando memoria. Con memCacheWidth e memCacheHeight si può decodificare l'immagine a una dimensione ridotta:
CachedNetworkImage(
imageUrl: thumbnailUrl,
memCacheWidth: 200,
memCacheHeight: 200,
fit: BoxFit.cover,
)
Questo riduce significativamente il consumo di RAM, soprattutto in liste e griglie con molte immagini.
Configurare la cache
Dietro le quinte, cached_network_image usa il pacchetto flutter_cache_manager. È possibile personalizzare durata e dimensione massima della cache creando un cache manager dedicato:
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
class CustomCacheManager {
static const key = 'customCache';
static final instance = CacheManager(
Config(
key,
stalePeriod: const Duration(days: 7),
maxNrOfCacheObjects: 200,
),
);
}
E poi passarlo al widget:
CachedNetworkImage(
imageUrl: imageUrl,
cacheManager: CustomCacheManager.instance,
)
In questo modo le immagini vengono rimosse dopo 7 giorni e non si superano mai i 200 file in cache.
Svuotare la cache
È utile fornire all'utente un'opzione per liberare spazio, oppure forzare il refresh di un'immagine aggiornata:
// Svuota tutta la cache
await DefaultCacheManager().emptyCache();
// Rimuove una singola immagine
await DefaultCacheManager().removeFile(imageUrl);
Best practice
- Usa sempre
placeholderederrorWidgetper evitare schermate vuote o crash visivi. - Imposta
memCacheWidth/memCacheHeightnelle liste per limitare il consumo di memoria. - Definisci un
stalePeriodcoerente con la frequenza di aggiornamento dei tuoi contenuti. - Per immagini che cambiano spesso allo stesso URL, valuta di aggiungere un parametro di versione o di rimuovere il file dalla cache.
- Combina con
BoxFit.covere unContainerdi sfondo per un layout stabile durante il caricamento.
Conclusione
cached_network_image è una libreria matura e semplice da integrare che migliora sensibilmente performance e percezione di fluidità della tua app. Con poche righe di codice ottieni cache su disco, placeholder, gestione errori e controllo fine sul consumo di memoria: un alleato indispensabile in qualsiasi app che mostri immagini di rete.
