Dependency Injection with GetIt in Flutter

- DI - Dependency injection - . ( D SOLID), . , , , .





, DI  - , . , , - . 





, , , . , , , . , .





GetIt. :   : Yandex.Weather VisualCrossing. , .





1. GetIt. , - - - - SharedPreferences. , . , -. 





GetIt main :





Future<void> main() async {  
  WidgetsFlutterBinding.ensureInitialized();  
  final settings = SettingsRepository();  
  await settings.loaded;  
  runApp(MyApp(settingsRepository: settings));
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key, required this.settingsRepository}) : super(key: key);

  final SettingsRepository settingsRepository;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        home: HomePage(settingsRepository: settingsRepository),
 ...
      );
  }
} 
      
class HomePage extends StatefulWidget {
  const HomePage({Key? key, required this.settingsRepository}) : super(key: key);

  final SettingsRepository settingsRepository;
...
      
      



GetIt , , .





Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  final settings = SettingsRepository();
  await settings.loaded;
  GetIt.instance.registerSingleton(settings);
  runApp(const MyApp());
}

class HomePage extends StatefulWidget {
  const HomePage({Key? key}) : super(key: key);

  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  SettingsRepository get settingsRepository => GetIt.instance.get<SettingsRepository>();
...
      
      



: . _HomePageState Geolocator. - - , DI. :





Future<void> _loadWeather() async {
    final knownPosition = await Geolocator.getLastKnownPosition();
    ...
  }
      
      



:





// main.dart
Future<void> main() async {
  ...
	final position = await geolocator.getLastKnownPosition();
  if (position != null) {
    GetIt.instance.registerSingleton<Position>(position); 
    //        ,        GPS
  }
  ...
    
// home_page.dart

Future<void> _loadWeather() async {
    final knownPosition = GetIt.instance.isRegistered<Position>() ? GetIt.instance.get<Position>() : null;
    ...
  }
      
      



, , http .. , , .





2. . , , , - . GetIt. , , , , - GetIt. 





:





Future<void> _loadWeather() async {
    final position = await Geolocator.getLastKnownPosition();
    final Map<DateTime, WeatherCondition> predictions;
    if (widget.settingsRepository.remoteServerName == YandexWeatherProvider.providerName) {
      predictions = await YandexWeatherProvider().loadPredictions(position?.latitude ?? 0.0, position?.longitude ?? 0.0);
    } else {
      predictions = await VisualCrossingWeatherProvider().loadPredictions(position?.latitude ?? 0.0, position?.longitude ?? 0.0);
    }
    currentWeather = predictions[DateTime.now().hourStart];
    setState(() {});
  }
      
      



:





//  main.dart
Future<void> main() async {
  ...
  GetIt.instance.registerSingleton<WeatherProvider>(settings.remoteServerName == YandexWeatherProvider.providerName ? YandexWeatherProvider() : VisualCrossingWeatherProvider());
  ...
}

...
//   
WeatherProvider get weatherProvider => GetIt.instance.get<WeatherProvider>();

Future<void> _loadWeather() async {
    final knownPosition = GetIt.instance.isRegistered<Position>() ? GetIt.instance.get<Position>() : null;
    final predictions = await weatherProvider.loadPredictions(knownPosition?.latitude ?? 0.0, knownPosition?.longitude ?? 0.0);
    currentWeather = predictions![DateTime.now().hourStart];
    setState(() {});
  }

...
//    
void _changeServer(String? value) {
    if (value == null) return;
    settingsRepository.remoteServerName = value;
    GetIt.instance.unregister<WeatherProvider>();
    GetIt.instance.registerSingleton<WeatherProvider>(value == YandexWeatherProvider.providerName ? YandexWeatherProvider() : VisualCrossingWeatherProvider());
    setState(() {});
  }
      
      



/ , .





3. mock- . -. BLoC , -. , - - SharedPreferences Geolocator , , . GetIt - mock- , , , Mockito .





class MockProvider extends Mock implements WeatherProvider {}

void main() {
  final repository = MockProvider();

  setUpAll(() {
    final service = GetIt.instance;
    service.registerSingleton<WeatherProvider>(repository);
  });

  testWidgets('   ', (WidgetTester tester) async {
    when(repository.loadPredictions(any, any)).thenAnswer((_) async {
      return {DateTime.now().hourStart: WeatherCondition(windDirection: WindDirection.north, temperature: 10.0, windSpeed: 3.0, windGust: 8.0)};
    });

    await tester.pumpWidget(const MaterialApp(
      home: HomePage(),
    ));
    await tester.pumpAndSettle();

    final titleText = find.text('Current weather:');
    expect(titleText, findsOneWidget);
    final weather = find.text(': 3.0 N,  8.0, : 10.0');
    expect(weather, findsOneWidget);
  });
}
      
      



GetIt . , , , , . , debug , release , .





. Dependency Injection : 









  • , - , 





  • mock- .








All Articles