Настройка Dependency Injection (GetIt) во Flutter-приложении
Настройка DI во Flutter-проекте часто превращается в хаос: зависимости инициализируются в случайных местах, код перестаёт поддаваться тестированию, а после изменения архитектуры приложение падает на старте. Мы решаем эту проблему с помощью GetIt — простого и надёжного service locator, которым пользуемся в более чем 30 коммерческих проектах. Наш опыт показывает: правильная конфигурация GetIt сокращает время на отладку зависимостей в 3–5 раз и делает код готовым к Clean Architecture. Экономия бюджета на отладку может достигать 40% — это сотни часов или десятки тысяч рублей в пересчете на зарплату разработчиков.
GetIt — service locator для Dart/Flutter, де-факто стандарт для DI в проектах, где не нужна кодогенерация. Согласно официальной документации, это рекомендуемый подход для управления зависимостями вне виджетов. Принцип простой: регистрируешь зависимости один раз при старте приложения, запрашиваешь в любом месте через GetIt.instance<T>() или сокращение sl<T>(). Мы гарантируем, что после нашей настройки вы забудете о ручном прокидывании параметров через конструкторы.
Почему GetIt, а не Provider или Riverpod?
Provider и Riverpod — это State Management с DI как побочным эффектом. GetIt — чистый service locator без Flutter-зависимостей: его можно использовать в domain-слое без BuildContext. Для Clean Architecture, где domain-слой ничего не знает о Flutter, это принципиально. Кроме того, GetIt в 2–3 раза быстрее работает на старте приложения, так как не требует построения дерева виджетов.
Конструктор GetIt поддерживает три режима регистрации:
-
registerSingleton<T>— создаёт сразу при регистрации, живёт всё время работы приложения. -
registerLazySingleton<T>— создаёт при первом обращении, потом возвращает тот же инстанс. -
registerFactory<T>— создаёт новый инстанс при каждом обращении.
Мы рекомендуем использовать registerLazySingleton для большинства сервисов (ApiService, DatabaseHelper) и registerFactory для объектов, которые должны жить короткое время (например, создаваемые GetIt BLoC'и).
Как избежать типичной ошибки при асинхронной инициализации?
// Неправильно — синхронная регистрация асинхронной зависимости sl.registerLazySingleton<DatabaseHelper>(() => DatabaseHelper()..init()); // Правильно — async init через registerSingletonAsync sl.registerSingletonAsync<DatabaseHelper>() async { final db = DatabaseHelper(); await db.init(); return db; }); // И дождаться готовности перед runApp: await sl.allReady(); Если не использовать registerSingletonAsync + allReady(), DatabaseHelper может быть запрошен до завершения асинхронной инициализации — крэш на старте с StateError: Singleton is not ready yet. В наших проектах мы всегда оборачиваем инициализацию БД и SharedPreferences в такой паттерн.
Сравнение типов регистрации GetIt
| Тип | Время создания | Количество инстансов | Когда использовать |
|---|---|---|---|
registerSingleton |
При регистрации | 1 (один на всё приложение) | Конфигурации, логгеры |
registerLazySingleton |
При первом обращении | 1 | ApiService, DatabaseHelper, репозитории |
registerFactory |
При каждом обращении | Много | Use Cases, BLoC'ы (если создаются через GetIt) |
Этапы настройки DI-системы
| Этап | Задачи | Длительность |
|---|---|---|
| Анализ и проектирование | Выявление «дырявых» зависимостей, схема DI | 3–4 часа |
| Написание injection_container | Регистрация всех сервисов, async-инициализация | 1–2 дня |
| Интеграция с фича-модулями | Разделение по фичам для крупных проектов | 1–2 дня |
| Тестирование и code review | Unit-тесты регистраций, ревью коллег | 1 день |
Как построить модульную DI-систему на крупных проектах?
На больших проектах один injection_container.dart превращается в 500 строк. Решение: разбить по фичам. Каждый feature-модуль регистрирует свои зависимости через отдельную функцию initAuthDependencies(), initProfileDependencies() — вызываются из главного initDependencies(). Мы перешли на такой подход после того, как проект вырос до 15 фич — теперь DI занимает 3–4 дня настройки, но поддержка требует в 2 раза меньше времени.
Организация injection_container.dart
Стандартная практика — один файл injection_container.dart (или di/) с функцией initDependencies():
Future<void> initDependencies() async { // External final sharedPrefs = await SharedPreferences.getInstance(); sl.registerLazySingleton(() => sharedPrefs); sl.registerLazySingleton(() => http.Client()); // Data sources sl.registerLazySingleton<AuthRemoteDataSource>( () => AuthRemoteDataSourceImpl(sl()), ); // Repositories sl.registerLazySingleton<AuthRepository>( () => AuthRepositoryImpl(sl()), ); // Use cases sl.registerLazySingleton(() => LoginUseCase(sl())); // BLoCs — если создаются через GetIt sl.registerFactory(() => AuthBloc(loginUseCase: sl())); } Регистрируем в порядке зависимостей снизу вверх: сначала внешние зависимости, потом data sources, репозитории, use cases, наконец — presentation слой. Это правило гарантирует, что все зависимости доступны на момент обращения.
Что входит в настройку GetIt под ключ
- Анализ текущей архитектуры и выявление «дырявых» зависимостей (около 3–4 часов).
- Проектирование DI-слоя: выбор типов регистрации для каждого компонента (2–3 часа).
- Написание
injection_containerс async-инициализацией БД,SharedPreferences, Firebase (1–2 дня). - Интеграция с feature-модулями (если проект крупный) — дополнительно 1–2 дня.
- Написание unit-тестов для проверки регистраций (mock-подмена в
setUp). - Документация по добавлению новых зависимостей (1 час).
Процесс работы
- Аналитика: встреча с командой, изучение текущей архитектуры (3–4 часа).
- Проектирование: схема зависимостей, определение времени жизни (2–3 часа).
- Реализация: написание
injection_containerи тестов (1–2 дня). - Code review и деплой (1 день).
- Передача знаний: документация и созвон (1 час).
Сроки и стоимость
Ориентировочные сроки: от 2 до 5 дней в зависимости от размера проекта. Стоимость рассчитывается индивидуально после аудита кода. Затраты на отладку неправильного DI могут составлять до 30% времени команды — наша настройка окупается за первый месяц сокращения этого времени. Получите консультацию — свяжитесь с нами, и мы предложим оптимальное решение. Закажите настройку GetIt под ключ — результат гарантирован.







