[{"data":1,"prerenderedAt":76},["ShallowReactive",2],{"tutorial-effettuare-chiamate-http-in-flutter-con-dio-intercettori-e-gestione-errori":3,"comments-tutorial-effettuare-chiamate-http-in-flutter-con-dio-intercettori-e-gestione-errori":75},{"id":4,"title":5,"slug":6,"excerpt":7,"intro":8,"cover_image":9,"video_url":10,"difficulty":11,"estimated_minutes":12,"flutter_version":13,"status":14,"published_at":15,"meta_title":16,"meta_description":17,"category":18,"author":22,"steps":24},23,"Effettuare chiamate HTTP in Flutter con Dio: intercettori e gestione errori","effettuare-chiamate-http-in-flutter-con-dio-intercettori-e-gestione-errori","Impara a usare il pacchetto Dio per gestire chiamate HTTP avanzate in Flutter: configurazione di base, intercettori per token e log, timeout e gestione centralizzata degli errori.","## Perché Dio?\n\nIl pacchetto `http` va benissimo per richieste semplici, ma quando il progetto cresce servono funzionalità più avanzate: **intercettori** per aggiungere automaticamente token di autenticazione, **gestione centralizzata degli errori**, **timeout configurabili** e **logging** delle richieste.\n\n[Dio](https:\u002F\u002Fpub.dev\u002Fpackages\u002Fdio) è uno dei client HTTP più potenti dell'ecosistema Flutter e risolve tutti questi problemi con un'API pulita.\n\nIn questo tutorial costruiremo un piccolo servizio che recupera dei post da una API pubblica, aggiungendo intercettori per il logging e l'autenticazione, oltre a una strategia robusta per la gestione delle eccezioni.","https:\u002F\u002Fflutter.it\u002Fstorage\u002Ftutorials\u002F64ef3c2e-6664-41e7-8533-c2a9992035a9.jpg",null,"intermediate",35,"3.x","published","2026-06-29T04:30:43+00:00","Chiamate HTTP in Flutter con Dio: intercettori ed errori","Guida pratica all'uso di Dio in Flutter: configurazione, intercettori per token e log, timeout e gestione centralizzata degli errori HTTP.",{"id":19,"name":20,"slug":21},1,"Guide","guide",{"id":19,"name":23},"Flutter Bot",[25,32,40,47,54,61,68],{"id":26,"position":19,"title":27,"body":28,"code_snippet":29,"code_language":30,"expected_result":31,"demo_url":10,"video_url":10},155,"Aggiungere la dipendenza Dio","Aggiungi il pacchetto `dio` al tuo progetto. Puoi farlo da terminale con il comando `flutter pub add dio` oppure inserendo manualmente la dipendenza nel file `pubspec.yaml`.\n\nDopo l'aggiunta, esegui `flutter pub get` per scaricare il pacchetto.","dependencies:\n  flutter:\n    sdk: flutter\n  dio: ^5.4.0","yaml","Il pacchetto Dio è installato e pronto per essere importato nel progetto.",{"id":33,"position":34,"title":35,"body":36,"code_snippet":37,"code_language":38,"expected_result":39,"demo_url":10,"video_url":10},156,2,"Creare un'istanza Dio configurata","Invece di creare nuove istanze sparse nel codice, è buona pratica centralizzare la configurazione di Dio in una classe dedicata. Qui impostiamo la `baseUrl`, i **timeout** di connessione e ricezione, e gli header di default.\n\nUsiamo come esempio l'API pubblica [JSONPlaceholder](https:\u002F\u002Fjsonplaceholder.typicode.com).","import 'package:dio\u002Fdio.dart';\n\nclass ApiClient {\n  final Dio dio;\n\n  ApiClient()\n      : dio = Dio(\n          BaseOptions(\n            baseUrl: 'https:\u002F\u002Fjsonplaceholder.typicode.com',\n            connectTimeout: const Duration(seconds: 10),\n            receiveTimeout: const Duration(seconds: 10),\n            headers: {\n              'Content-Type': 'application\u002Fjson',\n              'Accept': 'application\u002Fjson',\n            },\n          ),\n        );\n}","dart","Hai una classe ApiClient con un'istanza Dio configurata con base URL e timeout.",{"id":41,"position":42,"title":43,"body":44,"code_snippet":45,"code_language":38,"expected_result":46,"demo_url":10,"video_url":10},157,3,"Aggiungere un intercettore di logging","Gli **intercettori** permettono di eseguire codice prima dell'invio di una richiesta, alla ricezione di una risposta o in caso di errore. Un primo uso utile è il logging, per vedere in console le richieste effettuate.\n\nUsiamo `InterceptorsWrapper` e lo aggiungiamo alla lista `dio.interceptors`.","ApiClient() : dio = Dio(\u002F* ... BaseOptions ... *\u002F) {\n  dio.interceptors.add(\n    InterceptorsWrapper(\n      onRequest: (options, handler) {\n        print('--> ${options.method} ${options.uri}');\n        return handler.next(options);\n      },\n      onResponse: (response, handler) {\n        print('\u003C-- ${response.statusCode} ${response.requestOptions.uri}');\n        return handler.next(response);\n      },\n      onError: (error, handler) {\n        print('ERROR \u003C-- ${error.response?.statusCode} ${error.requestOptions.uri}');\n        return handler.next(error);\n      },\n    ),\n  );\n}","Ogni richiesta, risposta ed errore viene stampato nella console di debug.",{"id":48,"position":49,"title":50,"body":51,"code_snippet":52,"code_language":38,"expected_result":53,"demo_url":10,"video_url":10},158,4,"Aggiungere un intercettore per il token di autenticazione","Un secondo intercettore tipico inietta automaticamente il token di autenticazione in ogni richiesta, senza doverlo ripetere ad ogni chiamata. In un'app reale il token verrebbe letto da uno storage sicuro (es. `flutter_secure_storage`).\n\nQui simuliamo il recupero del token con un metodo `_getToken()`.","Future\u003CString?> _getToken() async {\n  \u002F\u002F In un'app reale: leggi da secure storage\n  return 'fake-jwt-token';\n}\n\nvoid _setupAuthInterceptor() {\n  dio.interceptors.add(\n    InterceptorsWrapper(\n      onRequest: (options, handler) async {\n        final token = await _getToken();\n        if (token != null) {\n          options.headers['Authorization'] = 'Bearer $token';\n        }\n        return handler.next(options);\n      },\n    ),\n  );\n}","Tutte le richieste includono automaticamente l'header Authorization quando il token è disponibile.",{"id":55,"position":56,"title":57,"body":58,"code_snippet":59,"code_language":38,"expected_result":60,"demo_url":10,"video_url":10},159,5,"Gestire gli errori in modo centralizzato","Dio lancia eccezioni di tipo `DioException`. Creiamo una classe di eccezione personalizzata e una funzione che traduce i vari tipi di errore (timeout, errori di rete, codici di stato HTTP) in messaggi comprensibili per l'utente.\n\nQuesto evita di duplicare la logica di gestione errori in ogni chiamata.","class ApiException implements Exception {\n  final String message;\n  final int? statusCode;\n  ApiException(this.message, {this.statusCode});\n\n  @override\n  String toString() => message;\n}\n\nApiException handleDioError(DioException e) {\n  switch (e.type) {\n    case DioExceptionType.connectionTimeout:\n    case DioExceptionType.receiveTimeout:\n    case DioExceptionType.sendTimeout:\n      return ApiException('Tempo di attesa scaduto. Riprova.');\n    case DioExceptionType.connectionError:\n      return ApiException('Nessuna connessione a Internet.');\n    case DioExceptionType.badResponse:\n      final code = e.response?.statusCode;\n      if (code == 404) return ApiException('Risorsa non trovata.', statusCode: 404);\n      if (code == 401) return ApiException('Non autorizzato.', statusCode: 401);\n      return ApiException('Errore del server ($code).', statusCode: code);\n    default:\n      return ApiException('Si è verificato un errore imprevisto.');\n  }\n}","Hai una funzione che converte qualsiasi DioException in un'ApiException con messaggio leggibile.",{"id":62,"position":63,"title":64,"body":65,"code_snippet":66,"code_language":38,"expected_result":67,"demo_url":10,"video_url":10},160,6,"Effettuare una chiamata GET con modello tipizzato","Mettiamo tutto insieme: definiamo un modello `Post`, e un metodo `fetchPosts()` che effettua la richiesta GET, mappa la risposta JSON in oggetti Dart e gestisce gli errori usando la funzione del passo precedente.\n\nNota l'uso di `try\u002Fcatch` per intercettare `DioException`.","class Post {\n  final int id;\n  final String title;\n  final String body;\n  Post({required this.id, required this.title, required this.body});\n\n  factory Post.fromJson(Map\u003CString, dynamic> json) => Post(\n        id: json['id'],\n        title: json['title'],\n        body: json['body'],\n      );\n}\n\nextension PostApi on ApiClient {\n  Future\u003CList\u003CPost>> fetchPosts() async {\n    try {\n      final response = await dio.get('\u002Fposts');\n      final data = response.data as List;\n      return data.map((e) => Post.fromJson(e)).toList();\n    } on DioException catch (e) {\n      throw handleDioError(e);\n    }\n  }\n}","Il metodo restituisce una lista di Post oppure lancia un'ApiException con messaggio chiaro.",{"id":69,"position":70,"title":71,"body":72,"code_snippet":73,"code_language":38,"expected_result":74,"demo_url":10,"video_url":10},161,7,"Usare il servizio nella UI","Infine, usiamo `FutureBuilder` per mostrare i dati nella UI, gestendo i tre stati: caricamento, errore e successo. Grazie alla gestione centralizzata, il messaggio d'errore mostrato all'utente è già leggibile.","class PostsScreen extends StatefulWidget {\n  const PostsScreen({super.key});\n  @override\n  State\u003CPostsScreen> createState() => _PostsScreenState();\n}\n\nclass _PostsScreenState extends State\u003CPostsScreen> {\n  final _api = ApiClient();\n  late final Future\u003CList\u003CPost>> _future = _api.fetchPosts();\n\n  @override\n  Widget build(BuildContext context) {\n    return Scaffold(\n      appBar: AppBar(title: const Text('Post')),\n      body: FutureBuilder\u003CList\u003CPost>>(\n        future: _future,\n        builder: (context, snapshot) {\n          if (snapshot.connectionState == ConnectionState.waiting) {\n            return const Center(child: CircularProgressIndicator());\n          }\n          if (snapshot.hasError) {\n            return Center(child: Text(snapshot.error.toString()));\n          }\n          final posts = snapshot.data!;\n          return ListView.builder(\n            itemCount: posts.length,\n            itemBuilder: (context, i) => ListTile(\n              title: Text(posts[i].title),\n              subtitle: Text(posts[i].body, maxLines: 2, overflow: TextOverflow.ellipsis),\n            ),\n          );\n        },\n      ),\n    );\n  }\n}","L'app mostra la lista dei post, un indicatore di caricamento durante la richiesta e un messaggio chiaro in caso di errore.",[],1785219610611]