Что такое Dependency Injection (DI) в Flutter?

«Что такое Dependency Injection (DI) в Flutter?» — вопрос из категории DI, который задают на 29% собеседований Flutter Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Dependency Injection — это паттерн, при котором зависимости объекта предоставляются извне, а не создаются внутри класса. В моих Flutter-проектах это критически важно для тестируемости и поддержки кода.

Практическая реализация в Dart/Flutter:

  1. Конструкторный DI (наиболее чистый подход):

    
    class UserRepository {
    final ApiService apiService;
    final LocalStorage storage;
    
    UserRepository({
    required this.apiService,
    required this.storage,
    });
    }

// Использование final repository = UserRepository( apiService: ApiService(baseUrl: 'https://api.example.com'), storage: HiveStorage(), );


2. **Использование пакетов для сложных случаев:**
- **GetIt** — сервис-локатор
- **Riverpod** — провайдер с встроенным DI
- **Injectable** — кодогенерация для DI

**Пример с GetIt:**
```dart
// setup_locator.dart
final getIt = GetIt.instance;

void setupDependencies() {
  getIt.registerLazySingleton<ApiService>(() => ApiService());
  getIt.registerFactory<UserRepository>(
    () => UserRepository(apiService: getIt<ApiService>()),
  );
}

// В приложении
void main() {
  setupDependencies();
  runApp(MyApp());
}

// В виджете
class UserProfile extends StatelessWidget {
  final UserRepository repo = getIt<UserRepository>();

  @override
  Widget build(BuildContext context) {
    // использование repo
  }
}

Преимущества из моего опыта:

  • Тестирование: легко подменять реальные сервисы моками
    test('UserRepository test', () {
    final mockApi = MockApiService();
    final repo = UserRepository(apiService: mockApi, storage: mockStorage);
    // тестируем изолированно
    });
  • Гибкость: изменение реализации без правки потребителей
  • Чистая архитектура: соблюдение принципа инверсии зависимостей (DIP)

В Flutter-контексте DI особенно важен для управления состоянием и сервисами, которые должны быть доступны во всем приложении.