Настройка Dependency Injection (Injectable) у Flutter-додатку
injectable — це кодогенератор поверх GetIt. Пишеш аннотації, build_runner генерує registration-код. Замість ручного injection_container.dart на 300 рядків — чистий декларативний код з @injectable, @singleton, @lazySingleton.
Навіщо injectable, якщо є GetIt
Ручна реєстрація у GetIt не масштабується: при 50+ залежностях потрібно стежити за порядком реєстрації, не забувати оновлювати injection_container при рефакторингу, розбиратися в чужих кастомних файлах. injectable усуває цей ручний труд — додав аннотацію до класу, запустив build_runner, файл *.config.dart оновився автоматично.
Базова настройка
pubspec.yaml:
dependencies:
get_it: ^7.6.0
injectable: ^2.3.0
dev_dependencies:
injectable_generator: ^2.4.0
build_runner: ^2.4.0
Точка входу:
// injection.dart
import 'package:get_it/get_it.dart';
import 'package:injectable/injectable.dart';
import 'injection.config.dart';
final sl = GetIt.instance;
@InjectableInit()
Future<void> configureDependencies() => sl.init();
Аннотація сервіса:
@lazySingleton
class ApiService {
final Dio _dio;
ApiService(this._dio); // injectable разберется с Dio автоматично
}
Запуск генерації: dart run build_runner build --delete-conflicting-outputs.
Environments: dev, staging, production
injectable підтримує @Environment аннотації — одна з головних причин вибрати його над чистим GetIt:
@dev
@LazySingleton(as: ApiService)
class MockApiService implements ApiService { ... }
@prod
@LazySingleton(as: ApiService)
class RealApiService implements ApiService { ... }
Ініціалізація з окруженням:
await configureDependencies(environment: Environment.prod);
У тестах — Environment.dev з моками. Не потрібно городити умови у injection_container.
Async dependencies
@singleton
class DatabaseService {
late final Database _db;
@factoryMethod
static Future<DatabaseService> create() async {
final service = DatabaseService();
service._db = await openDatabase('app.db');
return service;
}
}
@factoryMethod на static async-конструкторі — injectable сгенерує registerSingletonAsync. configureDependencies() вернет Future, потрібно await перед runApp.
Типична проблема при кодогенерації
Після додавання нового @injectable-класу розробник забуває запустити build_runner — додаток компілюється (старий .config.dart не видалений), але новий клас не зареєстрований. При першому звращенні — StateError: No instance of type XxxService found. Рішення: додати build_runner watch у процес розробки або налаштувати CI-крок перевірки актуальності сгенерованого коду.
Що входить у настройку
Додаємо залежності → створюємо точку входу з @InjectableInit → розставляємо аннотації по існуючим сервісам та репозиторіям → налаштовуємо environments для dev/prod → конфігуруємо build_runner у CI → перевіряємо async-залежності. При необхідності — рефакторинг ручного injection_container на аннотації.
Робота займає 1–3 дні залежно від розміру проекту. На новому проекті — швидше, на існуючому з ручним DI — довше через міграцію.







