get_it
| Package | Kind | Provides the role | Needs | Choose with |
|---|---|---|---|---|
smf_get_it | infrastructure | Dependency injection | nothing | -m get_it |
get_it provides dependency injection with get_it 9. The other modules of the app declare the services they generate, and this module registers them in get_it.
What it adds to the app
The module adds get_it: ^9.3.0 to the dependencies and generates lib/core/di/dependencies.dart with three functions. createServiceLocator() returns a service locator whose resolve finds the services in the global instance of get_it, GetIt.instance. registerDependencies() registers the services, and bootstrap() awaits it before the first frame. resetDependencies() resets get_it with GetIt.instance.reset(), for tests that register the services again.
Whichever module provides it, the dependency injection role adds lib/core/di/service_locator.dart with the ServiceLocator interface and the function resolve<T>(), and calls registerDependencies() in the DI phase of bootstrap().
In the guide for coding agents of the app, the dependency injection role describes the services under "Dependency injection". The module adds how registerDependencies() registers a service in get_it, and that no other file in lib/ imports the package.
How services are registered
A module declares each service by its type, the function that creates it, the services the function takes, and how long the service lives. registerDependencies() picks the get_it call that fits:
| A module declares | registerDependencies() calls |
|---|---|
| a singleton | registerSingleton |
| a singleton that waits for services that are created asynchronously or wait themselves | registerSingletonWithDependencies with dependsOn |
| a singleton created asynchronously | registerSingletonAsync, with dependsOn if it waits |
| a lazy singleton | registerLazySingleton |
| a factory | registerFactory |
| a name for one of several services of a type | instanceName, and InitDependency to wait for it |
| a function that disposes of a service | dispose |
The factory function of each service gets the services it declares from get_it. get_it creates a singleton while it registers it, so every service is registered after the services it takes or waits for. A singleton also waits, without declaring it, for the services it takes that are created asynchronously or wait themselves, directly or through lazy singletons and factories. When some services are created asynchronously, registerDependencies() completes once all of them are ready.
When resetDependencies() resets get_it, get_it disposes of the services it created, each with its dispose function, in the reverse order of their registration, so each service goes before the services it takes. A lazy singleton that nothing resolved is neither created nor disposed of. Then get_it removes every service, so that registerDependencies() can register them again.
dependencies.dart imports the file of every type and function it names with a prefix of its own, so the names of different modules never clash.
Using the services
Only the composition file of a feature, lib/features/<id>/<id>_composition.dart, takes services from the container with resolve, to create what the screens of the feature need, such as a Cubit. Everything else gets its services as parameters of its factory function. See Services and state.
Choosing it
smf create asks which module provides dependency injection and offers None as well. When a module you chose needs dependency injection and get_it is the only module that provides it, smf create adds get_it by itself. To choose it without the question:
smf create my_app -m get_it