如何在 flutter 中使用依赖注入?
How to use dependecy injection in flutter?
我想用di。在 flutter 中,我添加了这篇 https://pub.dartlang.org/packages/di packages my project and I started to read this https://webdev.dartlang.org/angular/guide/dependency-injection 文章,但我并不完全理解。
所以没关系:
在服务 class(例如:MyServices)上使用 @Injectable() 注解,但如何注入其他 class?
例如我想类似:
class MyClass{
//some variable
var asd = MyService.asd; //need inject var.
//maybe use injector.get(MyService).asd;
//but how add injector? (I don't add across constructor)
MyService.oneMethod;//need inject method
}
main(){
var injector = new ModuleInjector([new Module()
..bind(MyService)
]);
}
重点是,我不想使用构造函数。我想直接使用注射器。这在 flutter/dart?
中是可能的
Angulars DI 包不能独立于 Angular 使用。
di 包已经过时并且依赖于 dart:mirrors
而在 Flutter 中不可用
似乎有一个新的 DI 包正在进行中,它应该取代 Angulars 内置的 DI,并且应该也可以在 Flutter 或服务器端应用程序中独立使用,但没有预-发布或源代码可用。
更新
宣布的 DI 包被无限期推迟。
如果您想将 class 用作单例,据我所知,常见的用例是使用工厂构造函数。
How do you build a Singleton in Dart?
现在从不需要在 Flutter 中使用任何依赖注入系统。
最近 open-sourced Google 有一个 Flutter-compatible 依赖注入框架。可在此处获得:https://github.com/google/inject.dart
本项目提供静态compile-time依赖注入,而不是依赖反射在run-time处注入依赖。如果你熟悉Dagger,它看起来很相似。
值得注意 - 这不是官方 Google 或 Dart 团队项目。在撰写本文时,文档很少,目前被视为开发人员预览版。
我在这里遇到了同样的问题,所以我专门为 Flutter 创建了一个 dart 包。它依赖于工厂方法而不是镜像api,所以它在 flutter 中工作。同时仍然使用熟悉的 IOC 模式。希望这对您有所帮助!
https://pub.dartlang.org/packages/flutter_simple_dependency_injection
import 'package:flutter_simple_dependency_injection/injector.dart';
void main() {
final injector = Injector.getInjector();
injector.map(Logger, (i) => new Logger(), isSingleton: true);
injector.map(String, (i) => "https://api.com/", key: "apiUrl");
injector.map(SomeService, (i) => new SomeService(i.get(Logger), i.get(String, "apiUrl")));
injector.get(SomeService).doSomething();
// passing in the [SomeService] as a generic parameter strongly types the return object.
injector.get<SomeService>(SomeService).doSomething();
}
class Logger {
void log(String message) => print(message);
}
class SomeService {
final Logger _logger;
final String _apiUrl;
SomeService(this._logger, this._apiUrl);
void doSomething() {
_logger.log("Doing something with the api at '$_apiUrl'");
}
}
你好,这样的事情怎么样?很简单的实现,Injector 本身是单例的,也加入了 类 进去。当然可以很容易地扩展。如果您正在寻找更复杂的东西,请查看此包:https://pub.dartlang.org/packages/flutter_simple_dependency_injection
void main() {
Injector injector = Injector();
injector.add(() => Person('Filip'));
injector.add(() => City('New York'));
Person person = injector.get<Person>();
City city = injector.get<City>();
print(person.name);
print(city.name);
}
class Person {
String name;
Person(this.name);
}
class City {
String name;
City(this.name);
}
typedef T CreateInstanceFn<T>();
class Injector {
static final Injector _singleton = Injector._internal();
final _factories = Map<String, dynamic>();
factory Injector() {
return _singleton;
}
Injector._internal();
String _generateKey<T>(T type) {
return '${type.toString()}_instance';
}
void add<T>(CreateInstanceFn<T> createInstance) {
final typeKey = _generateKey(T);
_factories[typeKey] = createInstance();
}
T get<T>() {
final typeKey = _generateKey(T);
T instance = _factories[typeKey];
if (instance == null) {
print('Cannot find instance for type $typeKey');
}
return instance;
}
}
这个包 ioc_container 是一个 Dart Ioc 容器。从技术上讲,它不是注入器,因为它不会通过反射等方式自动注入。但是,它确实简化并组织了在您的工厂中注入依赖项的过程。这是代码。
代码here
import 'package:meta/meta.dart';
class ServiceDefinition<T> {
bool isSingleton;
T Function(IocContainer container) factory;
ServiceDefinition(this.isSingleton, this.factory);
}
class IocContainer {
@visibleForTesting
final Map<Type, ServiceDefinition> serviceDefinitionsByType;
@visibleForTesting
final Map<Type, Object> singletons;
IocContainer(this.serviceDefinitionsByType, this.singletons);
///Get an instance of your dependency
T get<T>() => singletons.containsKey(T)
? singletons[T] as T
: serviceDefinitionsByType.containsKey(T)
? (serviceDefinitionsByType[T]!.isSingleton
? singletons.putIfAbsent(
T,
() =>
serviceDefinitionsByType[T]!.factory(this) as Object) as T
: serviceDefinitionsByType[T]!.factory(this))
: throw Exception('Service not found');
}
///A builder for creating an [IocContainer].
class IocContainerBuilder {
final Map<Type, ServiceDefinition> _serviceDefinitionsByType = {};
///Throw an error if a service is added more than once. Set this to true when
///you want to add mocks to set of services for a test.
final bool allowOverrides;
IocContainerBuilder({this.allowOverrides = false});
///Add a factory to the container.
void addServiceDefinition<T>(
///Add a factory and whether or not this service is a singleton
ServiceDefinition<T> serviceDefinition) {
if (_serviceDefinitionsByType.containsKey(T)) {
if (allowOverrides) {
_serviceDefinitionsByType.remove(T);
} else {
throw Exception('Service already exists');
}
}
_serviceDefinitionsByType.putIfAbsent(T, () => serviceDefinition);
}
///Create an [IocContainer] from the [IocContainerBuilder].
///This will create an instance of each singleton service and store it
///in an immutable list unless you specify [isLazy] as true.
IocContainer toContainer(
{
///If this is true the services will be created when they are requested
///and this container will not technically be immutable.
bool isLazy = false}) {
if (!isLazy) {
final singletons = <Type, Object>{};
final tempContainer = IocContainer(_serviceDefinitionsByType, singletons);
_serviceDefinitionsByType.forEach((type, serviceDefinition) {
if (serviceDefinition.isSingleton) {
singletons.putIfAbsent(
type, () => serviceDefinition.factory(tempContainer));
}
});
return IocContainer(
Map<Type, ServiceDefinition>.unmodifiable(_serviceDefinitionsByType),
Map<Type, Object>.unmodifiable(singletons));
}
return IocContainer(
Map<Type, ServiceDefinition>.unmodifiable(_serviceDefinitionsByType),
<Type, Object>{});
}
}
extension Extensions on IocContainerBuilder {
///Add a singleton object dependency to the container.
void addSingletonService<T>(T service) =>
addServiceDefinition(ServiceDefinition(true, (i) => service));
void addSingleton<T>(T Function(IocContainer container) factory) =>
addServiceDefinition(ServiceDefinition(true, factory));
void add<T>(T Function(IocContainer container) factory) =>
addServiceDefinition(ServiceDefinition(false, factory));
}
我想用di。在 flutter 中,我添加了这篇 https://pub.dartlang.org/packages/di packages my project and I started to read this https://webdev.dartlang.org/angular/guide/dependency-injection 文章,但我并不完全理解。
所以没关系: 在服务 class(例如:MyServices)上使用 @Injectable() 注解,但如何注入其他 class? 例如我想类似:
class MyClass{
//some variable
var asd = MyService.asd; //need inject var.
//maybe use injector.get(MyService).asd;
//but how add injector? (I don't add across constructor)
MyService.oneMethod;//need inject method
}
main(){
var injector = new ModuleInjector([new Module()
..bind(MyService)
]);
}
重点是,我不想使用构造函数。我想直接使用注射器。这在 flutter/dart?
中是可能的Angulars DI 包不能独立于 Angular 使用。
di 包已经过时并且依赖于 dart:mirrors
而在 Flutter 中不可用
似乎有一个新的 DI 包正在进行中,它应该取代 Angulars 内置的 DI,并且应该也可以在 Flutter 或服务器端应用程序中独立使用,但没有预-发布或源代码可用。
更新
宣布的 DI 包被无限期推迟。
如果您想将 class 用作单例,据我所知,常见的用例是使用工厂构造函数。
How do you build a Singleton in Dart?
现在从不需要在 Flutter 中使用任何依赖注入系统。
最近 open-sourced Google 有一个 Flutter-compatible 依赖注入框架。可在此处获得:https://github.com/google/inject.dart
本项目提供静态compile-time依赖注入,而不是依赖反射在run-time处注入依赖。如果你熟悉Dagger,它看起来很相似。
值得注意 - 这不是官方 Google 或 Dart 团队项目。在撰写本文时,文档很少,目前被视为开发人员预览版。
我在这里遇到了同样的问题,所以我专门为 Flutter 创建了一个 dart 包。它依赖于工厂方法而不是镜像api,所以它在 flutter 中工作。同时仍然使用熟悉的 IOC 模式。希望这对您有所帮助!
https://pub.dartlang.org/packages/flutter_simple_dependency_injection
import 'package:flutter_simple_dependency_injection/injector.dart';
void main() {
final injector = Injector.getInjector();
injector.map(Logger, (i) => new Logger(), isSingleton: true);
injector.map(String, (i) => "https://api.com/", key: "apiUrl");
injector.map(SomeService, (i) => new SomeService(i.get(Logger), i.get(String, "apiUrl")));
injector.get(SomeService).doSomething();
// passing in the [SomeService] as a generic parameter strongly types the return object.
injector.get<SomeService>(SomeService).doSomething();
}
class Logger {
void log(String message) => print(message);
}
class SomeService {
final Logger _logger;
final String _apiUrl;
SomeService(this._logger, this._apiUrl);
void doSomething() {
_logger.log("Doing something with the api at '$_apiUrl'");
}
}
你好,这样的事情怎么样?很简单的实现,Injector 本身是单例的,也加入了 类 进去。当然可以很容易地扩展。如果您正在寻找更复杂的东西,请查看此包:https://pub.dartlang.org/packages/flutter_simple_dependency_injection
void main() {
Injector injector = Injector();
injector.add(() => Person('Filip'));
injector.add(() => City('New York'));
Person person = injector.get<Person>();
City city = injector.get<City>();
print(person.name);
print(city.name);
}
class Person {
String name;
Person(this.name);
}
class City {
String name;
City(this.name);
}
typedef T CreateInstanceFn<T>();
class Injector {
static final Injector _singleton = Injector._internal();
final _factories = Map<String, dynamic>();
factory Injector() {
return _singleton;
}
Injector._internal();
String _generateKey<T>(T type) {
return '${type.toString()}_instance';
}
void add<T>(CreateInstanceFn<T> createInstance) {
final typeKey = _generateKey(T);
_factories[typeKey] = createInstance();
}
T get<T>() {
final typeKey = _generateKey(T);
T instance = _factories[typeKey];
if (instance == null) {
print('Cannot find instance for type $typeKey');
}
return instance;
}
}
这个包 ioc_container 是一个 Dart Ioc 容器。从技术上讲,它不是注入器,因为它不会通过反射等方式自动注入。但是,它确实简化并组织了在您的工厂中注入依赖项的过程。这是代码。
代码here
import 'package:meta/meta.dart';
class ServiceDefinition<T> {
bool isSingleton;
T Function(IocContainer container) factory;
ServiceDefinition(this.isSingleton, this.factory);
}
class IocContainer {
@visibleForTesting
final Map<Type, ServiceDefinition> serviceDefinitionsByType;
@visibleForTesting
final Map<Type, Object> singletons;
IocContainer(this.serviceDefinitionsByType, this.singletons);
///Get an instance of your dependency
T get<T>() => singletons.containsKey(T)
? singletons[T] as T
: serviceDefinitionsByType.containsKey(T)
? (serviceDefinitionsByType[T]!.isSingleton
? singletons.putIfAbsent(
T,
() =>
serviceDefinitionsByType[T]!.factory(this) as Object) as T
: serviceDefinitionsByType[T]!.factory(this))
: throw Exception('Service not found');
}
///A builder for creating an [IocContainer].
class IocContainerBuilder {
final Map<Type, ServiceDefinition> _serviceDefinitionsByType = {};
///Throw an error if a service is added more than once. Set this to true when
///you want to add mocks to set of services for a test.
final bool allowOverrides;
IocContainerBuilder({this.allowOverrides = false});
///Add a factory to the container.
void addServiceDefinition<T>(
///Add a factory and whether or not this service is a singleton
ServiceDefinition<T> serviceDefinition) {
if (_serviceDefinitionsByType.containsKey(T)) {
if (allowOverrides) {
_serviceDefinitionsByType.remove(T);
} else {
throw Exception('Service already exists');
}
}
_serviceDefinitionsByType.putIfAbsent(T, () => serviceDefinition);
}
///Create an [IocContainer] from the [IocContainerBuilder].
///This will create an instance of each singleton service and store it
///in an immutable list unless you specify [isLazy] as true.
IocContainer toContainer(
{
///If this is true the services will be created when they are requested
///and this container will not technically be immutable.
bool isLazy = false}) {
if (!isLazy) {
final singletons = <Type, Object>{};
final tempContainer = IocContainer(_serviceDefinitionsByType, singletons);
_serviceDefinitionsByType.forEach((type, serviceDefinition) {
if (serviceDefinition.isSingleton) {
singletons.putIfAbsent(
type, () => serviceDefinition.factory(tempContainer));
}
});
return IocContainer(
Map<Type, ServiceDefinition>.unmodifiable(_serviceDefinitionsByType),
Map<Type, Object>.unmodifiable(singletons));
}
return IocContainer(
Map<Type, ServiceDefinition>.unmodifiable(_serviceDefinitionsByType),
<Type, Object>{});
}
}
extension Extensions on IocContainerBuilder {
///Add a singleton object dependency to the container.
void addSingletonService<T>(T service) =>
addServiceDefinition(ServiceDefinition(true, (i) => service));
void addSingleton<T>(T Function(IocContainer container) factory) =>
addServiceDefinition(ServiceDefinition(true, factory));
void add<T>(T Function(IocContainer container) factory) =>
addServiceDefinition(ServiceDefinition(false, factory));
}