[{"data":1,"prerenderedAt":77},["ShallowReactive",2],{"tutorial-iniezione-delle-dipendenze-in-flutter-con-get-it-e-injectable":3,"comments-tutorial-iniezione-delle-dipendenze-in-flutter-con-get-it-e-injectable":76},{"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":25},32,"Iniezione delle dipendenze in Flutter con get_it e injectable","iniezione-delle-dipendenze-in-flutter-con-get-it-e-injectable","Impara a strutturare le dipendenze della tua app Flutter con un service locator basato su get_it e a generarle automaticamente con injectable per un codice pulito e testabile.","Quando un'app Flutter cresce, gestire manualmente la creazione di servizi, repository e client HTTP diventa rapidamente ingestibile. La **Dependency Injection (DI)** risolve questo problema disaccoppiando la creazione di un oggetto dal suo utilizzo.\n\nIn questo tutorial useremo [`get_it`](https:\u002F\u002Fpub.dev\u002Fpackages\u002Fget_it), un service locator semplice e veloce, insieme a [`injectable`](https:\u002F\u002Fpub.dev\u002Fpackages\u002Finjectable), che genera automaticamente il codice di registrazione tramite annotazioni. Il risultato è un'architettura più pulita, testabile e scalabile.\n\nVedremo come registrare singleton, factory e dipendenze asincrone, come gestire ambienti diversi (dev\u002Fprod) e come iniettare i servizi nei widget.","https:\u002F\u002Fflutter.it\u002Fstorage\u002Ftutorials\u002F23c035fa-51a4-4353-9e25-7ea2299afb93.jpg",null,"intermediate",35,"3.x","published","2026-07-08T04:30:43+00:00","Dependency Injection in Flutter con get_it e injectable","Guida pratica alla dependency injection in Flutter: configura get_it e injectable per registrare servizi, singleton e factory con codice generato.",{"id":19,"name":20,"slug":21},3,"Best practice","best-practice",{"id":23,"name":24},1,"Flutter Bot",[26,33,41,47,55,62,69],{"id":27,"position":23,"title":28,"body":29,"code_snippet":30,"code_language":31,"expected_result":32,"demo_url":10,"video_url":10},216,"Aggiungere le dipendenze al progetto","Per prima cosa aggiungiamo i pacchetti necessari. `get_it` è il service locator a runtime, mentre `injectable` fornisce le annotazioni. Servono anche `injectable_generator` e `build_runner` come dipendenze di sviluppo per generare il codice.\n\nAggiungi le seguenti voci al file `pubspec.yaml` oppure usa i comandi `flutter pub add`.","dependencies:\n  get_it: ^7.7.0\n  injectable: ^2.4.4\n\ndev_dependencies:\n  build_runner: ^2.4.13\n  injectable_generator: ^2.6.2","yaml","Dopo `flutter pub get` i pacchetti sono installati e pronti all'uso.",{"id":34,"position":35,"title":36,"body":37,"code_snippet":38,"code_language":39,"expected_result":40,"demo_url":10,"video_url":10},217,2,"Configurare il container get_it","Creiamo un file `injection.dart` che espone l'istanza globale di `GetIt` e la funzione di inizializzazione. L'annotazione `@InjectableInit` indica a injectable dove generare il codice di configurazione.\n\nIl file generato si chiamerà `injection.config.dart` e conterrà l'estensione `init` che registra tutte le dipendenze annotate.","import 'package:get_it\u002Fget_it.dart';\nimport 'package:injectable\u002Finjectable.dart';\n\nimport 'injection.config.dart';\n\nfinal getIt = GetIt.instance;\n\n@InjectableInit(\n  initializerName: 'init',\n  preferRelativeImports: true,\n  asExtension: true,\n)\nvoid configureDependencies() => getIt.init();","dart","Il file compilerà con un errore su 'injection.config.dart' finché non lanceremo il generatore: è normale.",{"id":42,"position":19,"title":43,"body":44,"code_snippet":45,"code_language":39,"expected_result":46,"demo_url":10,"video_url":10},218,"Annotare i servizi da iniettare","Ora creiamo i servizi. Usiamo `@lazySingleton` per un'istanza unica creata alla prima richiesta, ideale per client di rete e repository. Con `@injectable` (factory) invece si ottiene una nuova istanza ad ogni `get`.\n\nNota come `UserRepository` dipende da `ApiClient`: injectable risolve automaticamente le dipendenze nel costruttore, purché anch'esse siano registrate.","import 'package:injectable\u002Finjectable.dart';\n\n@lazySingleton\nclass ApiClient {\n  Future\u003CString> fetchName() async {\n    await Future.delayed(const Duration(milliseconds: 300));\n    return 'Mario Rossi';\n  }\n}\n\n@lazySingleton\nclass UserRepository {\n  final ApiClient _api;\n\n  UserRepository(this._api);\n\n  Future\u003CString> getUserName() => _api.fetchName();\n}","I servizi sono annotati e verranno riconosciuti dal generatore al passo successivo.",{"id":48,"position":49,"title":50,"body":51,"code_snippet":52,"code_language":53,"expected_result":54,"demo_url":10,"video_url":10},219,4,"Generare il codice con build_runner","Con le annotazioni in posizione, lanciamo il generatore di codice. Il comando analizza il progetto e crea `injection.config.dart` con tutte le registrazioni.\n\nUsa il flag `--delete-conflicting-outputs` per sovrascrivere eventuali file generati in precedenza senza errori.","flutter pub run build_runner build --delete-conflicting-outputs","bash","Viene creato il file `injection.config.dart` e l'errore di import nel passo 2 scompare.",{"id":56,"position":57,"title":58,"body":59,"code_snippet":60,"code_language":39,"expected_result":61,"demo_url":10,"video_url":10},220,5,"Inizializzare la DI nel main","Prima di avviare l'app dobbiamo popolare il container. Chiamiamo `configureDependencies()` nel `main`, dopo `WidgetsFlutterBinding.ensureInitialized()` (necessario se registri dipendenze asincrone o usi plugin).\n\nDa questo momento qualsiasi punto dell'app potrà recuperare i servizi con `getIt\u003CTipo>()`.","import 'package:flutter\u002Fmaterial.dart';\nimport 'injection.dart';\n\nvoid main() {\n  WidgetsFlutterBinding.ensureInitialized();\n  configureDependencies();\n  runApp(const MyApp());\n}","L'app si avvia e tutte le dipendenze sono registrate nel container get_it.",{"id":63,"position":64,"title":65,"body":66,"code_snippet":67,"code_language":39,"expected_result":68,"demo_url":10,"video_url":10},221,6,"Utilizzare i servizi in un widget","Recuperiamo `UserRepository` dal service locator e usiamolo in un `FutureBuilder`. Evita di chiamare `getIt` direttamente nel `build`: recuperalo una sola volta in `initState` o in un campo `final`, così eviti lookup ripetuti ad ogni rebuild.\n\nQuesto approccio mantiene i widget disaccoppiati dalla logica di creazione delle dipendenze.","class HomePage extends StatefulWidget {\n  const HomePage({super.key});\n\n  @override\n  State\u003CHomePage> createState() => _HomePageState();\n}\n\nclass _HomePageState extends State\u003CHomePage> {\n  final _repo = getIt\u003CUserRepository>();\n\n  @override\n  Widget build(BuildContext context) {\n    return Scaffold(\n      appBar: AppBar(title: const Text('DI con get_it')),\n      body: Center(\n        child: FutureBuilder\u003CString>(\n          future: _repo.getUserName(),\n          builder: (context, snapshot) {\n            if (!snapshot.hasData) {\n              return const CircularProgressIndicator();\n            }\n            return Text('Utente: ${snapshot.data}');\n          },\n        ),\n      ),\n    );\n  }\n}","Dopo un breve caricamento la schermata mostra 'Utente: Mario Rossi'.",{"id":70,"position":71,"title":72,"body":73,"code_snippet":74,"code_language":39,"expected_result":75,"demo_url":10,"video_url":10},222,7,"Gestire ambienti diversi con @Environment","Un vantaggio della DI è poter fornire implementazioni diverse in base all'ambiente. Definiamo un'interfaccia e due implementazioni annotate con `@Environment`: una per lo sviluppo (dati finti) e una per la produzione.\n\nAl momento dell'inizializzazione passiamo l'environment desiderato a `getIt.init(environment: ...)`, aggiornando la firma di `configureDependencies`. Questo è utilissimo anche per iniettare mock nei test.","import 'package:injectable\u002Finjectable.dart';\n\nabstract class ConfigService {\n  String get baseUrl;\n}\n\n@Environment('dev')\n@LazySingleton(as: ConfigService)\nclass DevConfigService implements ConfigService {\n  @override\n  String get baseUrl => 'https:\u002F\u002Fdev.api.example.com';\n}\n\n@Environment('prod')\n@LazySingleton(as: ConfigService)\nclass ProdConfigService implements ConfigService {\n  @override\n  String get baseUrl => 'https:\u002F\u002Fapi.example.com';\n}\n\n\u002F\u002F injection.dart aggiornato\nvoid configureDependencies(String env) => getIt.init(environment: env);\n\n\u002F\u002F main.dart\n\u002F\u002F configureDependencies('dev');","In base all'environment passato, get_it registra l'implementazione corretta di ConfigService. Ricorda di rilanciare build_runner dopo le modifiche.",[],1785219609291]