I searched for "Dependency Injection" and looked at the top ~10 or so on pub.dev.
class AppModule extends Module {
@override
List<Bind> get binds => [
Bind.factory((i) => XPTOEmail())
Bind.factory<EmailService>((i) => XPTOEmailService(i()))
Bind.singleton((i) => Client(i()))
];
// ...
}
final client = Modular.get<Client>();
// Or with a default value
final client = Modular.get<Client>(defaultValue: Client());
- Supports other types of Flutter-specific utilities, like around build context and routing
- Seems to support hot reloading, but not clear how unique this is.
// Singleton.
KiwiContainer container = KiwiContainer();
// Not a singleton.
KiwiContainer container = KiwiContainer.scoped();
container.registerInstance(Sith('Anakin', 'Skywalker'));
container.registerInstance(Sith('Anakin', 'Skywalker'), name: 'DartVader');
container.registerInstance<Character>(Sith('Anakin', 'Skywalker'), name: 'DartVader');
Sith theSith = container.resolve<Sith>();
Sith theSith = container.resolve<Sith>('DartVader');
Sith theSith = container.resolveAs<Character, Sith>();
- Includes code generation for factory generation
- Allows hiding errors
// Initializing a text string instance through a method toInstance()
Binding<String>().toInstance('hello world');
// Initializing a text string instance
Binding<String>().toProvide(() => 'hello world');
// Initializing an instance of a string named
Binding<String>().withName('my_string').toInstance('hello world');
class AppModule extends Module {
@override
void builder(Scope currentScope) {
bind<ApiClient>().toInstance(ApiClientMock());
}
}
final str = rootScope.resolve<String>();
final str = rootScope.tryResolve<String>();
// Import the service provider
import 'my_entrypoint.catalyst_builder.g.dart';
@GenerateServiceProvider()
void main() {
// Create a new instance of the service provider
var provider = DefaultServiceProvider();
// Boot it to wire services
provider.boot();
// Resolve a service.
var myService1 = provider.resolve<MyService>();
// Inferred types are also supported
MyService myService2 = provider.resolve();
}
@Service()
@Preload()
class MyService {
MyService() {
print('Service was created');
}
}
void main() {
ServiceProvider provider;
provider.boot(); // prints "Service was created"
provider.resolve<MyService>(); // Nothing printed
}
void main() {
/// create a Scope
Scope()
/// inject values
..value<int>(ageKey, 18)
..value<int>(heightKey, 182) // centimetres
/// single value from factory method
..single<Db>(incomeKey, () => calcIncome)
/// sequence of values from factory method.
..sequence<int>(countKey, () => tracker)
/// run some code within the Scope
..run(() => a();
}
void printRealWorth() {
print('You are the ${use(countKey)} person to ask');
print('You are ${use(ageKey)} years old');
print('You earn ${use(incomeKey} per hour.');
}
final repoModule = Module([
single<GithubRepo>(({params}) => GithubRepo(get<GithubService>())),
]);
final remoteModule = Module([
single<GithubService>(({params}) => GithubService()),
]);
final appModule = [viewModelModule, repoModule, remoteModule];
//default
final service = inject<GithubService>();
//pass parameters
final test = inject<HomeProvide>(params: ['title']);
//different scope
final test = inject<HomeProvide>(scope:test,params: ['title']);
final appModule = {
single((i) => Api()),
single<Repository>((i) => MyRepository(i.get())),
factory((i) => UseCase(i.get())),
factoryWithParams((i, p) => ViewModel(i.get(), p["dynamicParam"])),
};
final _loginViewModel = Stark.get<LoginViewModel>();
There are a reasonable amount of existing dependency injection and inversion of control (IoC)-style packages; some are opinionated (either Flutter only, or deep integration with Flutter), and others are generic; some are entirely runtime based, some have optional code generation, and yet others require code generation.
Typically, the documentation is lighter than you'd want for a concept such as dependency injection, but Dart as a whole has a more immature package ecosystem, and this isn't a specific issue to dependency injection.
In terms of Dart idiomatic, this is where almost every solution does something different or even surprising.