Nella precedente lezione abbiamo analizzato in dettaglio il widget Image
e visto alcuni esempi pratici per caricare un immagine in locale.
Nonostante l’utilizzo degli asset sia fondamentale durante lo sviluppo di qualsiasi app, non sempre possiamo sfruttare questo approccio per il caricamento e la visualizzazione delle immagini. Oggigiorno, è diventata prassi comune utilizzare immagini e dati forniti da un servizio di backend con cui la nostra app si interfaccia per ottenere i dati necessari a popolare l’interfaccia utente.
In questa lezione vederemo nel dettaglio come caricare un immagine da internet e come salvarla in cache per renderla visibile all'untete anche quando è offline.
Visualizzazione di un’immagine da internet
Tra i costruttori offerti dal widget Image ritroviamo il costruttore Image.network
che permette il caricamento di immagini e GIF animate usando un URL.
Per iniziare creiamo un nuovo progetto come mostrato nella lezione 6 di questa guida e lasciando inalterati gli import
, il metodo main()
e la classe MyApp
, cancelliamo il resto per aggiungere il seguente StatelessWidget
composto da uno Scaffold
per la definizione dell’AppBar
e di una SingleChildScrollView
(di cui abbiamo già parlato nella lezione 11) che conterrà i nostri esempi pratici di caricamento delle immagini.
class MyPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Lesson 12 - Assets and Images'),
),
body: SingleChildScrollView(
child: Column(
children: <Widget>[
//we will add our widgets here.
],
)),
);
}
}
Modifichiamo infine la classe MyApp
per impostare il widget appena creato come home.
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
// . . .
home: MyPage(),
);
}
}
Un semplice esempio di caricamento di un’immagine in rete tramite il costruttore Image.network
è ad esempio il seguente.
children: <Widget>[
// . . .
Container(
color: Colors.black,
child: Image.network(
'https://www.html.it/app/themes/html-2018/dist/images/logo-open.png'
),
)
],
Come si può evincere dal codice riportato abbiamo passato come parametro del costruttore un URL che identifica univocamente la nostra risorsa al posto del percorso nella cartella assets. Eseguendo l’applicazione, otterremo quindi il seguente risultato.
Figura 71. Caricamento di un’immagine dal web per a) Android e b) iOS
In modo analogo se volessimo caricare una GIF animata, non dovremmo cambiare nulla all'interno del nostro codice se non la URL di riferimento. Vediamo un esempio.
children: <Widget>[
// . . .
Container(
child: Image.network(
'https://media.giphy.com/media/9LQHvkbIzTSLe/giphy.gif'),
)
],
Eseguendo l'applicazione vedremo, il corretto caricamento della GIF.
Figura 72a. Caricamento di una GIF da internet per Android
Figura 72b. Caricamento di una GIF da internet per iOS
Visualizzare e salvare in cache un’immagine da internet
In alcuni casi, è però necessario memorizzare in cache le immagini quando vengono caricate dal Web in modo da poterle visualizzare anche quando si è offline. Per raggiungere tale scopo la community di Flutter offre il package cached_network_image
.
Questo package definisce al suo interno il widget CachedNetworkImage
e CachedNetworkImageProvider
il cui scopo è proprio quello di caricare un’immagine da internet e salvarla in cache.
Per poter usare questa libreria è necessario aggiungere all’interno del file pubspec.yml la dipendenza
dependencies:
cached_network_image: ^0.8.0
e cliccare su Package get per effettuare l’aggiornamento delle dipendenze.
A questo punto possiamo importare la libreria nel file main.dart ed utilizzare il widget CachedNetworkImage
come segue.
import 'package:cached_network_image/cached_network_image.dart';
children: <Widget>[
// . . .
Container(
color: Colors.black,
child: CachedNetworkImage(
imageUrl: 'https://www.html.it/app/themes/html-2018/dist/images/logo-open.pn'
),
)
]
Eseguiamo l'applicazione ottenendo il seguente risultato
Figura 73a. Caricamento di un’immagine da internet e salvataggio in cache per Android
Figura 73b. Caricamento di un’immagine da internet e salvataggio in cache per iOS
L'immagine è stata caricata dalla rete, ma mettendo la modalità aereo e ricaricando l'applicazione abbiamo che l'immagine sarà comununque visualizzata correttamente, cosa che non avviene per le immagini caricate tramite il costruttore Image.network
.
Analizzando in dettaglio le proprietà offerte dal widget CachedNetworkImage
possiamo notare due proprietà estremamente utili:
Proprietà | Tipo Accettato | Descrizione |
---|---|---|
errorWidget |
LoadingErrorWidgetBuilder |
definisce un widget da mostare quando fallisce il caricamento dell'immagine |
placeholder |
PlaceholderWidgetBuilder |
definisce un widget da mostrare finchè non viene cariacta l'immagine che prenderà il posto di questo placeholder |
Definiamo, quindi, un widget CachedNetworkImage
che definisca l’immagine da caricare ed:
- un widget di caricamento circolare da visualizzare come placeholder finchè l'immagine non sarà caricata;
- un’icona di errore qualora ci dovessero essere problemi nel caricamento dell'immagine.
Per farlo definiamo nella nostra app il seguente codice:
children: <Widget>[
// . . .
Container(
color: Colors.black,
child: CachedNetworkImage(
imageUrl:
'https://www.html.it/app/themes/html-2018/dist/images/logo-open.png',
placeholder: (context, url) => new CircularProgressIndicator(),
errorWidget: (context, url, error) => new Icon(
Icons.error,
color: Colors.red,
),
),
),
]
Eseguiamo l’applicazione, per vedere il risultato di questa modifica.
Figura 74a. Caricamento di un’immagine da internet con relativo placeholder
e errorWidget
per Android
Figura 74b. Caricamento di un’immagine da internet con relativo placeholder
e errorWidget
per iOS
Come si può notare l’immagine caricata è identica alle precedenti versioni, ma con l'importante differenza che finché l’immagine non sarà visualizzata verrà mostrato un'icona di caricamento e, in caso di problemi di caricamento, verrà visualizzata un’icona di errore.
Infine per rendere più graduale il passaggio tra il placeholder e l'immagine caricata, è fortemente consigliato l'utilizzo di una breve dissolvenza. Per farlo, possiamo sfruttare la proprietà fadeInDuration
che ci permette di definere la durata della dissolvenza.
Aggiungiamo all'esempio precedente la seguente riga di codice.
fadeInDuration: Duration(seconds: 3),
Eseguendo nuovamente l’app, otterremo il seguente risultato in cui è visibile l'effetto dissolvenza.
Figura 75a. Caricamento di un’immagine da internet con un effetto dissolvenza tra il placeholder e l'immagine per Android
Figura 75b. Caricamento di un’immagine da internet con un effetto dissolvenza tra il placeholder e l'immagine per iOS
Il codice di questa lezione è disponibile su GitHub.