What does serviceLocator() mean in GetIt?

44 views Asked by At

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.

1

There are 1 answers

0
Dhruvin Vainsh On BEST ANSWER

The short answer it's the combination of the callable class and type-inferance.

  1. callable classes: By 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');
  }
}
  1. type-inferance: by specifying the return type 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>