[{"data":1,"prerenderedAt":22},["ShallowReactive",2],{"articolo-iniezione-delle-dipendenze-in-flutter-con-get-it-e-injectable":3,"comments-article-iniezione-delle-dipendenze-in-flutter-con-get-it-e-injectable":21},{"id":4,"title":5,"slug":6,"excerpt":7,"body":8,"cover_image":9,"video_url":10,"status":11,"published_at":12,"meta_title":13,"meta_description":14,"category":15,"author":19},11,"Iniezione delle dipendenze in Flutter con get_it e injectable","iniezione-delle-dipendenze-in-flutter-con-get-it-e-injectable","Impara a strutturare la dependency injection in Flutter usando get_it come service locator e injectable per la generazione automatica del codice, con esempi pratici e best practice.","## Perché la Dependency Injection in Flutter\n\nLa **Dependency Injection** (DI) è un pattern che consente di fornire a una classe le sue dipendenze dall'esterno, invece di crearle internamente. In un'app Flutter ben strutturata, questo porta a numerosi vantaggi:\n\n- **Disaccoppiamento**: le classi non dipendono dalle implementazioni concrete.\n- **Testabilità**: è facile sostituire le dipendenze reali con dei mock nei test.\n- **Manutenibilità**: la configurazione delle dipendenze è centralizzata.\n\nIn questo articolo vedremo come implementare la DI usando due pacchetti molto popolari: `get_it`, un service locator leggero e veloce, e `injectable`, che genera automaticamente il codice di registrazione.\n\n## Installazione delle dipendenze\n\nAggiungi i pacchetti al tuo `pubspec.yaml`:\n\n```yaml\ndependencies:\n  get_it: ^7.7.0\n  injectable: ^2.4.4\n\ndev_dependencies:\n  injectable_generator: ^2.6.2\n  build_runner: ^2.4.13\n```\n\n## Configurazione di base con get_it\n\n`get_it` da solo permette di registrare e recuperare le dipendenze in modo manuale. L'oggetto centrale è l'istanza `GetIt`:\n\n```dart\nimport 'package:get_it\u002Fget_it.dart';\n\nfinal getIt = GetIt.instance;\n\nvoid setupLocator() {\n  \u002F\u002F Singleton: la stessa istanza per tutta l'app\n  getIt.registerSingleton\u003CApiClient>(ApiClient());\n\n  \u002F\u002F Lazy singleton: creato solo al primo utilizzo\n  getIt.registerLazySingleton\u003CAuthRepository>(\n    () => AuthRepository(getIt\u003CApiClient>()),\n  );\n\n  \u002F\u002F Factory: nuova istanza ad ogni richiesta\n  getIt.registerFactory\u003CLoginBloc>(\n    () => LoginBloc(getIt\u003CAuthRepository>()),\n  );\n}\n```\n\nPer recuperare una dipendenza basta scrivere `getIt\u003CAuthRepository>()`.\n\n## Automatizzare la registrazione con injectable\n\nScrivere a mano tutte le registrazioni diventa rapidamente noioso e soggetto a errori. `injectable` risolve il problema generando il codice tramite annotazioni.\n\n### Configurare l'entry point\n\nCrea un file `injection.dart`:\n\n```dart\nimport 'package:get_it\u002Fget_it.dart';\nimport 'package:injectable\u002Finjectable.dart';\nimport 'injection.config.dart';\n\nfinal getIt = GetIt.instance;\n\n@InjectableInit()\nvoid configureDependencies() => getIt.init();\n```\n\nIl metodo `getIt.init()` viene generato automaticamente nel file `injection.config.dart`.\n\n### Annotare le classi\n\nUsa le annotazioni per indicare come registrare ciascuna classe:\n\n```dart\nimport 'package:injectable\u002Finjectable.dart';\n\n@singleton\nclass ApiClient {\n  final String baseUrl = 'https:\u002F\u002Fapi.example.com';\n}\n\n@lazySingleton\nclass AuthRepository {\n  final ApiClient apiClient;\n\n  AuthRepository(this.apiClient);\n\n  Future\u003Cbool> login(String email, String password) async {\n    \u002F\u002F logica di autenticazione\n    return true;\n  }\n}\n\n@injectable\nclass LoginBloc {\n  final AuthRepository authRepository;\n\n  LoginBloc(this.authRepository);\n}\n```\n\nLe annotazioni principali sono:\n\n- `@injectable`: registra una factory (nuova istanza ogni volta).\n- `@singleton`: registra un singleton creato immediatamente.\n- `@lazySingleton`: singleton creato al primo accesso.\n\n### Generare il codice\n\nEsegui il comando:\n\n```bash\ndart run build_runner build --delete-conflicting-outputs\n```\n\nQuesto genera `injection.config.dart` con tutte le registrazioni. Ricorda di chiamare `configureDependencies()` nel `main`:\n\n```dart\nvoid main() {\n  configureDependencies();\n  runApp(const MyApp());\n}\n```\n\n## Registrare interfacce e implementazioni\n\nUn pattern molto comune è dipendere da astrazioni. Con `@Injectable(as:)` puoi legare un'interfaccia alla sua implementazione:\n\n```dart\nabstract class UserService {\n  Future\u003CUser> getUser(String id);\n}\n\n@Injectable(as: UserService)\nclass UserServiceImpl implements UserService {\n  @override\n  Future\u003CUser> getUser(String id) async {\n    \u002F\u002F implementazione concreta\n    return User(id: id);\n  }\n}\n```\n\nA questo punto richiederai `getIt\u003CUserService>()` ottenendo l'implementazione concreta, senza accoppiamento diretto.\n\n## Gestire dipendenze asincrone\n\nAlcune dipendenze richiedono un'inizializzazione asincrona, come `SharedPreferences`. Usa `@preResolve`:\n\n```dart\n@module\nabstract class RegisterModule {\n  @preResolve\n  Future\u003CSharedPreferences> get prefs => SharedPreferences.getInstance();\n}\n```\n\nIn questo caso `configureDependencies()` deve diventare asincrono:\n\n```dart\n@InjectableInit()\nFuture\u003Cvoid> configureDependencies() => getIt.init();\n\nvoid main() async {\n  WidgetsFlutterBinding.ensureInitialized();\n  await configureDependencies();\n  runApp(const MyApp());\n}\n```\n\n## Ambienti e mock per i test\n\n`injectable` supporta gli ambienti, utilissimi per i test. Puoi annotare classi con `@Environment`:\n\n```dart\n@Environment('test')\n@Injectable(as: UserService)\nclass MockUserService implements UserService {\n  @override\n  Future\u003CUser> getUser(String id) async => User(id: 'mock');\n}\n```\n\nE nei test inizializzare con l'ambiente desiderato:\n\n```dart\nvoid main() {\n  setUp(() {\n    configureDependencies(environment: 'test');\n  });\n\n  \u002F\u002F ... i tuoi test\n}\n```\n\n## Best practice\n\n- **Centralizza la configurazione**: mantieni un unico punto di setup delle dipendenze.\n- **Dipendi da astrazioni**: usa interfacce per facilitare il testing.\n- **Evita di abusare del service locator** dentro i widget: preferisci passare le dipendenze tramite costruttori o combinare get_it con un sistema di state management.\n- **Resetta get_it nei test** con `getIt.reset()` tra un test e l'altro per evitare effetti collaterali.\n\n## Conclusioni\n\nLa combinazione di `get_it` e `injectable` offre un sistema di dependency injection potente, conciso e con un boilerplate minimo grazie alla generazione automatica del codice. Adottare la DI fin dall'inizio del progetto rende l'architettura più pulita, modulare e soprattutto facilmente testabile, elementi fondamentali per un'app Flutter scalabile.","https:\u002F\u002Fflutter.it\u002Fstorage\u002Farticles\u002F903e83ec-2391-410f-84e5-5e075fd6dbba.jpg",null,"published","2026-06-14T04:00:37+00:00","Dependency Injection in Flutter con get_it e injectable","Guida pratica alla dependency injection in Flutter: usa get_it come service locator e injectable per generare il codice di registrazione automaticamente.",{"id":16,"name":17,"slug":18},1,"Guide","guide",{"id":16,"name":20},"Flutter Bot",[],1781420706620]