Ricevere dei dati da internet é una funzionalità necessaria per la maggior parte delle applicazioni. Fortunatamente, Dart e Flutter forniscono strumenti, quali il pacchetto http, per questa necessità.

In questo esempio seguiremo questi passi:

  1. Aggiungere il pacchetto http
  2. Fare una richiesta alla rete utilizzando il pacchetto http
  3. Convertire la risposta in un oggetto Dart
  4. Ricevere e mostrare i dati con Flutter.

1. Aggiungere il pacchetto http

Il pacchetto http fornisce il modo più semplice per ricevere dati da internet.

Per installare il pacchetto http, aggiungerlo nella sezione dipendenze del file pubspec.yaml. Si può reperire l'ultima versione del pacchetto http in pub.dev

dependencies:
  http: <latest_version>

Importare il pacchetto http

import 'package:http/http.dart' as http;

In aggiunta, nel file AndroidManifest.xml, aggiungere i permessi internet

<!-- Necessario per ricevere dati da internet. -->
<uses-permission android:name="android.permission.INTERNET" />

2. Inviare una richiesta alla rete

Nell'esempio mostreremo come ottenere un album di esempio da JSONPlaceholder utilizzando il metodo http.get()

Future fetchAlbum() {
  return http.get('https://jsonplaceholder.typicode.com/albums/1');
}

Il metodo http.get() restituisce una Future che contiene un Response.

  • Future è una classe chiave di Dart per lavorare con le operazioni asincrone. Un oggetto Future rappresenta un potenziale valore o errore che sarà disponibile ad un certo momento nel futuro.
  • La classe http.Response contiene i dati ricevuti da una chiamata http andata a buon fine.

3. Convertire la risposta in un oggetto Dart

Effettuare una chiamata di rete è semplice, ma lavorare un Future<http.Response> grezzo non e' molto comodo. Per semplificarci il lavoro, convertire l' http.Response in un oggetto Dart.

Creare una classe Album

Per prima cosa, creare una classe Album che contiene i dati della richiesta di rete. Include un costruttore factory che crea un album da JSON

class Album {
  final int userId;
  final int id;
  final String title;

  Album({this.userId, this.id, this.title});

  factory Album.fromJson(Map json) {
    return Album(
      userId: json['userId'],
      id: json['id'],
      title: json['title'],
    );
  }
}

Convertire http.Response in un Album

Ora seguiamo questi passi per aggiornare la funzione fetchAlbum() di modo che restituisca un Future<Album>

  1. Convertire il corpo della risposta in una Map JSON con il pacchetto dart:convert
  2. Se il server restituisce una risposta OK con un codice stato 200, allora lancia un'eccezione. (anche in caso di un "404 Not found" lancia un eccezione. Non restituire NULL. Questo è importante quando si esaminano i dati in uno snapshot, come mostrato qui sotto)
import 'dart:convert';

Future<Album> fetchAlbum() async {
  final response = await http.get('https://jsonplaceholder.typicode.com/albums/1');

  if (response.statusCode == 200) {
    // Se il server ha restituito una risposta 200 OK,
    // allora anlizza il JSON.
    return Album.fromJson(jsonDecode(response.body));
  } else {
    // Se il server non ha restituito una risposta 200 OK,
    // allora lancia un'eccezione.
    throw Exception('Caricamento Album fallito');
  }
}

Ora abbiamo una funzione che riceve un album da internet


4. Ricevere i dati

Chiamare il metodo fetch() nel metodo initState() o nel metodo didChangeDependencies()

Il metodo initState() viene chiamato una volta sola e mai piu. Se vuoi avere la possibilita di ricaricare l' API in risposta a un cambiamento di InheritWidget, puoi inserire la chiamata nel metodo didChangeDependencies.

class _MyAppState extends State<MyApp> {
  Future<Album> futureAlbum;

  @override
  void initState() {
    super.initState();
    futureAlbum = fetchAlbum();
  }
  

Questa Future viene utilizzata nel prossimo passo.


5. Mostrare i dati

Per mostrare i dati sullo schermo, utilizzare il widget FutureBuilder. Il widget FutureBuilder è integrato in Flutter e rende facile lavorare con sorgenti di dati asincrone.

È necessario fornire due parametri:

  1. La Future con cui volete lavorare. In questo caso la future restituita dalla funzione fetchAlbum().
  2. una funzione builder che dica a Flutter cosa mostrare, a seconda dello stato della Future: loading, success o error.

Nota: snapshot.hasData restituisce true solo quando lo snapshot contiene un valore non nullo. Qeusto è il motivo per cui la funzione fetchAlbum deve lanciare un eccezione anche in caso di un responso del server "404 not found". Se fetchAlbum restituisce null allora lo spinner viene mostrato indefinitamente.

FutureBuilder(
  future: futureAlbum,
  builder: (context, snapshot) {
    if (snapshot.hasData) {
      return Text(snapshot.data.title);
    } else if (snapshot.hasError) {
      return Text("${snapshot.error}");
    }

    // Come default, mostra uno spinner di caricamento
    return CircularProgressIndicator();
  },
);

Perchè fetchAlbum viene chiamato in initState()?

Anche se conveniente, non e' consigliabile mettere una chiamata API in un metodo buil*().

Flutter chiam ail metodo build() ogni volta che deve cambiare qualcosa nella vierw, e questo accade molto spesso. Lasciare la chiamata fetch nel metodo build inonderebbe l' API con chiamate non necessarie e rallenterebbe l'applicazione.


Il codice completo

import 'dart:async';
import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;

Future<Album> fetchAlbum() async {
  final response =
      await http.get('https://jsonplaceholder.typicode.com/albums/1');

  if (response.statusCode == 200) {
    // Se il server ha restituito una risposta 200 OK,
    // allora anlizza il JSON.
    return Album.fromJson(jsonDecode(response.body));
  } else {
    // Se il server non ha restituito una risposta 200 OK,
    // allora lancia un'eccezione.
    throw Exception('Caricamento Album fallito');
  }
}

class Album {
  final int userId;
  final int id;
  final String title;

  Album({this.userId, this.id, this.title});

  factory Album.fromJson(Map<String, dynamic> json) {
    return Album(
      userId: json['userId'],
      id: json['id'],
      title: json['title'],
    );
  }
}

void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
  MyApp({Key key}) : super(key: key);

  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  Future<Album> futureAlbum;

  @override
  void initState() {
    super.initState();
    futureAlbum = fetchAlbum();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Esempio Ricezione Dati',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Scaffold(
        appBar: AppBar(
          title: Text('Esempio Ricezione Dati'),
        ),
        body: Center(
          child: FutureBuilder<Album>(
            future: futureAlbum,
            builder: (context, snapshot) {
              if (snapshot.hasData) {
                return Text(snapshot.data.title);
              } else if (snapshot.hasError) {
                return Text("${snapshot.error}");
              }

              // Come default, mostra uno spinner di caricamento
              return CircularProgressIndicator();
            },
          ),
        ),
      ),
    );
  }
}




Copyright © 2024.
Tutti i diritti riservati. outsourcingasia.it
TECHCONSULTI CO. LTD.

Copyright © 2024. Tutti i diritti riservati. outsourcingasia.it - TECHCONSULTI CO. LTD.