I am trying to master GetIt. First I read the official documentation. Then I came to articles by different authors. Finally, I took a working code to get some practice.
And I don't understand the following. I have code that works great:
final serviceLocator = GetIt.instance;
setupServiceLocator() async {
serviceLocator.registerFactory<Constant>(() => Constant());
serviceLocator.registerFactory<Dio>(
() => NetworkClient(Dio(), constant: serviceLocator()).dio,
);
// News
serviceLocator.registerFactory<MainNewsBloc>(() => MainNewsBloc());
serviceLocator.registerLazySingleton<NewsApi>(() => NewsApi(
dio: serviceLocator(), apiKey: serviceLocator<Constant>().apiKey));
serviceLocator.registerLazySingleton<NewsRepository>(() => NewsRepositoryImpl(
newsApi: serviceLocator(), apiKey: serviceLocator<Constant>().apiKey));
serviceLocator.registerLazySingleton<GetRecentNewsUseCase>(
() => GetRecentNewsUseCase(serviceLocator()));
}
I understand lines like:
serviceLocator.registerFactory<Constant>(() => Constant());
...
serviceLocator.registerFactory<MainNewsBloc>(() => MainNewsBloc());
But I don't understand lines like:
serviceLocator.registerLazySingleton<NewsApi>(() => NewsApi(
dio: serviceLocator(), apiKey: serviceLocator<Constant>().apiKey));
In particular, I don't understand the following:
dio: serviceLocator(),
...
newsApi: serviceLocator(),
...
serviceLocator.registerLazySingleton<GetRecentNewsUseCase>(
() => GetRecentNewsUseCase(serviceLocator()));
Why is serviceLocator() used in all these cases? What does this mean?
Of course, I should ask this question to the author of this code. But I believe that there are enough experienced programmers here to explain to me what serviceLocator() means as arguments in all these cases.
The short answer it's the combination of the callable
class and type-inferance.
serviceLocator()
in this kind of syntax, you are invoking a method with the name call
inside the object.To understand this you can refer to this code example:
void main(List<String> args) {
const callable = CallableClass();
callable();
}
class CallableClass {
const CallableClass();
void call() {
print('invoked call method inside callable class');
}
}
T
of a generic function you are passing the type parameter as T
to that function type param.The internal implementation of get_It looks like this:
@override
T call<T extends Object>({
String? instanceName,
dynamic param1,
dynamic param2,
}) {
return get<T>(instanceName: instanceName, param1: param1, param2: param2);
}
for understanding consider the following dart snipper:
void main(List<String> args) {
final int value = findWhereTypeIsT();
print(value); // 10
}
T findWhereTypeIsT<T>() {
final objects = <Object>[10, "something"];
return objects.whereType<T>().first;
}
And according to get it docs: Callable class so that you can write GetIt.instance<MyType>
instead of GetIt.instance.get<MyType>