Un numero sempre maggiore di app sfrutta servizi web remoti per presentare all’utente
informazioni quali: testo, immagini video, … Non solo le app dei social media (Instagram,
Tik Tok, Twitter, …), ma anche molte altre app “informative” utilizzano il protocollo HTTP
per scambiarsi informazioni. Di conseguenza sempre più linguaggi (oggi praticamente tutti)
prevedono appositi meccanismi (librerie, pacchetti, moduli, …) per il recupero di informazioni
mediante richieste HTTP, dart non fa eccezione e a tal scopo mette a disposizione il
pacchetto http.
In questo laboratorio impareremo ad usare il meccanismo di programmazione asincrona async/await
di
dart per recuperare dati attraverso richieste HTTP utilizzando il modulo http.dart
.
Import di http.dart
Come ogni pacchetto dart, il primo passo per l’utilizzo di un pacchetto è la sua dichiarazione
tra le dependencies nel file pubspec.yaml
dependencies:
# Requires most recent http package compatible with version 0.13.0
http: ^0.13.0
Una volta inserito nel pubspec
il pacchetto può essere importato nel file sorgente
import 'package:http/http.dart' as http;
Creazione di un Uri
Per avviare una richiesta in http.dart
si usa la funzione get
la quale richiede
(a partire dalla versione 0.13
) come parametro un oggetto di tipo Uri.
Tale oggetto può essere creato usando i costruttori con cone Uri.http
o Uri.https
,
questi costruttori possono essere utilizzati con 1, 2 o 3 parametri
Uri.http(
String authority,
[String unencodedPath,
Map<String, dynamic>? queryParameters]
)
I tre parametri rappresentano:
- l’authority cioè il sito da contattare, ad esempio
www.googleapis.com
; - il path per il servizio o la risorsa richiesta, ad esempio
/books/v1/volumes
; - l’insieme dei parametri (coppie chiave-valore) da usare per la query, ad esempio
{'q': '{http}'}
.
final url = Uri.https(
'www.googleapis.com',
'/books/v1/volumes',
{'q': '{http}'},
);
Esercizio
Tramite il seguente link https://api.chucknorris.io/jokes/random
è possibile recuperare una barzelletta su Chuck Norris, crea un oggetto Uri
che possa
utilizzato per una richiesta a questa API (nota che non ci sono parametri da passare).
Richiesta: http.get
Dopo aver creato l’oggetto Uri
per la richiesta HTTP, questo può essere utilizzato
per avviare una richiesta utilizzando la funzione asincrona get
. Questa funzione
è asincrona e quindi restituisce un Future<Response>
. Oltre all’Uri
obbligatorio,
la funzione get
ha un secondo parametro opzionale che è una Map<String,String>
per
indicare gli header della richiesta http.
Attenzione
La funzione get
è una funzione asincrona che è meglio gestita con il meccanismo
async/await
. Bisogna, tuttavia, ricordarsi che l’oggetto ritornato non è un
Future
quando si utilizza await
final r = http.get(uri); // r è Future<Response>
print(r); // Instance of '_Future<Response>'
final r await http.get(uri); // r è Response
print(r); // Instance of 'Response'
Esercizio
Utilizzando l’oggetto Uri
definito nell’esercizio precedente, generare una richiesta
HTTP utilizzando la funzione get
e memorizzare l’oggetto Response
risultate in una
variabile.
Gestione dello status code
Spesso una richiesta HTTP non va a buon fine, i motivi possono essere svariati (connessione,
richiesta malformata, mancanza di permessi, …), per questo motivo il primo passo da
fare una volta ricevuto la risposta è controllare lo status code della richiesta. L’oggetto Response
restituito da get
permette il controllo tramite
la variabile di classe statusCode
.
if (response.statusCode == 200) { // HTTP 200 -> Ok
print('Request Ok');
} else {
print('Request error, status: ${response.statusCode}');
}
Esercizio
Aggiungere al programma il controllo dello status code restituito da get
, ricorda
che solo usando await
si avrà accesso diretto alla variabile di tipo Response
.
Decodifica del file JSON
Il contenuto della risposta (nel caso di successo con status code 200
) è disponibile
nella variabile body
della risposta
Questo contenuto è spesso in formato JSON, fortunatamente
Dart fornisce un modo veloce per convertire una stringa contenente un JSON in un oggetto di
tipo Map<String,dynamic>
.
Innanzitutto dobbiamo importare il modulo dart:convert
import 'dart:convert' as convert;
a questo punto possiamo usare la funzione jsonDecode
per decodificare una stringa in un JSON
final jsonResponse = convert.jsonDecode(response.body);
infine possiamo accedere alle parti del JSON utilizzando la struttura associativa jsonResponse
print(jsonResponse['key']);
Esercizio
In caso di successo, le API su Chuck Norris restituiscono un JSON contenente, tra gli altri campi,
una barzelletta, questa si trova nel campo value
del JSON. Completare il programma scritto
finora affinché, in caso di successo della richiesta HTTP, stampi la barzelletta ricevuta.