|
| 1 | +--- |
| 2 | +id: service-locator |
| 3 | +title: Service Locator |
| 4 | +sidebar_label: Service Locator |
| 5 | +sidebar_position: 1 |
| 6 | +tags: [service-locator, dependency-registration, location-service] |
| 7 | +--- |
| 8 | + |
| 9 | +# What is a Service Locator? |
| 10 | + |
| 11 | +The main idea of the Service Locator is to create a registry containing all the dependencies and get components from it whenever we need them. Every object that needs something from this registry will interact with it rather than trying to instantiate a dependency itself. However, the object will still have a dependency, but only for the Service Locator itself, and it will provide us with the needed implementation transparently. |
| 12 | + |
| 13 | +Using `dependencies` property in `StackedApp` annotation we can set a list of `DependencyRegistration` type as following. |
| 14 | + |
| 15 | +```dart |
| 16 | +@StackedApp( |
| 17 | +dependencies: [ |
| 18 | + Singleton(classType: NavigationService), |
| 19 | + LazySingleton(classType: ThemeService, resolveUsing: ThemeService.getInstance), |
| 20 | + LazySingleton(classType: FirebaseAuthService, asType: AuthService), |
| 21 | + InitializableSingleton(classType: SharedPreferencesService), |
| 22 | + Factory(classType: FactoryService), |
| 23 | + ], |
| 24 | +) |
| 25 | +``` |
| 26 | + |
| 27 | +## Dependency Types |
| 28 | + |
| 29 | +Below we describe all dependency types that can be registered as a dependency in the `StackedApp` annotation. |
| 30 | + |
| 31 | +### Singleton |
| 32 | + |
| 33 | +It provides a way to register an object as a Singleton to the service locator. A Singleton means the object will be instantiated during the first fetch and then will stay alive in the memory and the same instance will be returned in the subsequent fetches. |
| 34 | + |
| 35 | +| Parameter | Description | |
| 36 | +| ------------ | ----------- | |
| 37 | +| classType | The concrete class to be registered to the service locator. | |
| 38 | +| asType | An abstract class or interface to map the **classType** to. This is useful when you want to abstract the concrete implementation and depend on interfaces. | |
| 39 | +| resolveUsing | A callback that resolves the instance. If null, **classType** is instantiated directly. | |
| 40 | +| environments | A set of environment names where this registration should be included. Useful for conditionally including a service depending on the running environment. | |
| 41 | +| instanceName | An optional instance name that can be used to register multiple objects of the same type. You will need to fetch the object by instance name from the service locator. | |
| 42 | + |
| 43 | +### LazySingleton |
| 44 | + |
| 45 | +It provides a way to register an object as a Lazy Singleton to the service locator. A Lazy Singleton means the object will be instantiated during the first fetch and then will stay alive in the memory and the same instance will be returned in the subsequent fetches. The key difference between a `Singleton` and a `LazySingleton` is that a Lazy Singleton is not created until it is fetched for the first time. |
| 46 | + |
| 47 | +| Parameter | Description | |
| 48 | +| ------------ | ----------- | |
| 49 | +| classType | The concrete class to be registered to the service locator. | |
| 50 | +| asType | An abstract class or interface to map the **classType** to. This is useful when you want to abstract the concrete implementation and depend on interfaces. | |
| 51 | +| resolveUsing | A callback that resolves the instance. If null, **classType** is instantiated directly. | |
| 52 | +| environments | A set of environment names where this registration should be included. Useful for conditionally including a service depending on the running environment. | |
| 53 | +| instanceName | An optional instance name that can be used to register multiple objects of the same type. You will need to fetch the object by instance name from the service locator. | |
| 54 | + |
| 55 | +### InitializableSingleton |
| 56 | + |
| 57 | +It provides a way to register an object as a Singleton to the service locator. This means the object will be instantiated during the first fetch and then will stay alive in the memory and the same instance will be returned in the subsequent fetches. |
| 58 | + |
| 59 | +When used with a class implementing the `InitializableDependency` interface, the `init` method of the class will be called upon registration, allowing any necessary asynchronous initialization logic to be executed before the singleton instance is fetched for the first time. This is useful when you need to perform some setup or initialization task (like setting up a database, making a network request, etc.) before the class can be used. |
| 60 | + |
| 61 | +| Parameter | Description | |
| 62 | +| ------------ | ----------- | |
| 63 | +| classType | The concrete class to be registered to the service locator. This class should implement **InitializableDependency** interface. | |
| 64 | +| asType | An abstract class or interface to map the **classType** to. This is useful when you want to abstract the concrete implementation and depend on interfaces. | |
| 65 | +| environments | A set of environment names where this registration should be included. Useful for conditionally including a service depending on the running environment. | |
| 66 | +| instanceName | An optional instance name that can be used to register multiple objects of the same type. You will need to fetch the object by instance name from the service locator. | |
| 67 | + |
| 68 | +### Factory |
| 69 | + |
| 70 | +It provides a way to register an object as a Factory to the service locator. A Factory means that a new instance of the object will be created each time it is fetched. |
| 71 | + |
| 72 | +| Parameter | Description | |
| 73 | +| ------------ | ----------- | |
| 74 | +| classType | The concrete class to be registered to the service locator. | |
| 75 | +| asType | An abstract class or interface to map the **classType** to. This is useful when you want to abstract the concrete implementation and depend on interfaces. | |
| 76 | +| environments | A set of environment names where this registration should be included. Useful for conditionally including a service depending on the running environment. | |
| 77 | +| instanceName | An optional instance name that can be used to register multiple objects of the same type. You will need to fetch the object by instance name from the service locator. | |
| 78 | + |
| 79 | +### FactoryWithParam |
| 80 | + |
| 81 | +It provides a way to register an object as a Factory with parameters to the service locator. A Factory with parameters means that a new instance of the object will be created each time it is fetched, and the parameters will be passed to the factory function to create the instance. |
| 82 | + |
| 83 | +| Parameter | Description | |
| 84 | +| ------------ | ----------- | |
| 85 | +| classType | The concrete class to be registered to the service locator. | |
| 86 | +| asType | An abstract class or interface to map the **classType** to. This is useful when you want to abstract the concrete implementation and depend on interfaces. | |
| 87 | +| environments | A set of environment names where this registration should be included. Useful for conditionally including a service depending on the running environment. | |
| 88 | +| instanceName | An optional instance name that can be used to register multiple objects of the same type. You will need to fetch the object by instance name from the service locator. | |
| 89 | + |
| 90 | +## Environments |
| 91 | + |
| 92 | +It is possible to register different dependencies for different environments by using `environments: {Environment.dev}` in the below example `NavigationService` is now only registered if we pass the environment name to `setupLocator(environment: Environment.dev);`. |
| 93 | + |
| 94 | +```dart |
| 95 | +LazySingleton( |
| 96 | + classType: NavigationService, |
| 97 | + environments: {Environment.dev}, |
| 98 | +), |
| 99 | +``` |
| 100 | + |
| 101 | +Now passing your environment to `setupLocator` function will create a simple environment filter that will only validate dependencies that have no environments or one of their environments matches the given environment. Alternatively, you can pass your own EnvironmentFilter to decide what dependencies to register based on their environment keys, or use one of the shipped ones |
| 102 | + |
| 103 | +* NoEnvOrContainsAll |
| 104 | +* NoEnvOrContainsAny |
| 105 | +* SimpleEnvironmentFilter |
0 commit comments