Dagger 2 - 如何 create/provide 一个 EagerSingleton
Dagger 2 - how to create/provide a EagerSingleton
我在使用 Dagger 2 依赖项注入框架时遇到问题。我想创建一个 EagerSingleton。当我使用 @Singleton
注释时,我假设 dagger 2 创建了延迟加载的单例。如何使用 Dagger 2 框架创建 EagerSingleton?
我知道怎么做了:
根据 docs dagger 不直接支持 eagerSingletons 所以:
通过创建一个 EagerSingletons class 来解决这个问题,它为每个热切的单例声明静态字段。
方法注入.
所以我在任何我想使用急切单例的模块中创建了一个 EagerSingletons class。在那个 eagerSingletons class 中,我会声明我想使用的任何单例。就这样吧,dagger 然后让单身狗跃跃欲试。
更新:我以匕首 1 为例的原因是它在匕首 2 中是这样做的。确实没有针对 eagerSingleton 的机制。你必须使用静态字段来实现它。让我举例说明如何创建 eagerSingleton:
In every module you need a eager singleton you could have this:
//assume this file is called myModule.java
static EagerObjects eagerObjects;
public static void initEagerObjects() {
if (eagerObjects == null) {
eagerObjects = new EagerObjects();
}
}
//so far so good, only one object will be created, lets inject what we need immediately
public static class EagerObjects {
public EagerObjects() {
//inject right away,you'll have to figure out a way to pass the graph in. by constructor param should be fine
getGraph().inject(this);
}
//make this injection static
@Inject
static CoffeePot coffeePot;
}
}
现在想办法在应用程序启动时立即调用它....
回到你的匕首组件或你扩展的应用程序class你可以有一个静态方法来调用每个模块的每一个:
static void injectAllEagerObjects() {
myModule.initEagerObjects();
someOtherModule.initEagerObjects();
//...all of them can be here since there static
}
现在我们差不多完成了,只需在应用程序启动时调用它。
因此,在您从应用程序创建图形之后,您必须立即调用 injectAllEagerObjects() (如果需要,可能会在那里传递图形实例)。这将以正确的方式且仅初始化一次渴望的单例。
说了这么多,我希望 dagger 有一个你可以像这样使用的注释:
@singleton(eager=true) 但静态字段,这是他们目前推荐的。
我通过创建一个 EagerModule
解决了这个问题,它有一个返回 Void
的单一提供方法。我急切地创建了所有我想要的东西,并将其指定为该方法的参数。然后我向组件添加了一个 Void init()
方法,我在创建组件后立即调用该方法。
@Module
public class EagerModule {
@Provides
@Nullable
Void provideEager(...) {
// this eagerly builds any parameters specified and returns nothing
return null;
}
}
@Component(modules = {EagerModule.class})
public interface TestComponent {
@Nullable
Void init();
}
这显然不会让您访问热切创建的单例,但对于我的使用,我不需要访问,我只是想创建它们。
这是我为 Dagger2 提出的可复制粘贴示例,我认为没有办法避免(冗余地)在组件中声明哪些模块具有急切对象。
如果有人能提供一个不那么样板的例子就好了。
Main.java
import dagger.Component;
import dagger.Module;
import dagger.Provides;
import javax.inject.Inject;
import javax.inject.Singleton;
public class Main {
public static void main(String[] args) {
TestComponent component = DaggerTestComponent.create();
System.out.println("Created component.");
component.createEagerSingletons();
}
}
@Component(modules = {TestModule1.class, TestModule2.class})
@Singleton
abstract class TestComponent {
abstract EagerSingletons createEagerSingletons();
static class EagerSingletons {
@Inject EagerSingletons() { System.out.println("Building all eager objects.."); }
@Inject TestModule1.EagerSingletons m1;
@Inject TestModule2.EagerSingletons m2;
}
}
@Module
class TestModule1 {
static class Thing1 { @Inject Thing1(){}}
static class Thing2 { @Inject Thing2(){}}
@Provides
@Singleton
Thing1 first() { return new Thing1(); }
@Provides
@Singleton
Thing2 secon() { return new Thing2(); }
static class EagerSingletons {
@Inject Thing1 a;
@Inject Thing2 b;
@Inject EagerSingletons() { System.out.println("[1] Eagerly built objects!"); }
}
}
@Module
class TestModule2 {
static class EagerSingletons {
@Inject EagerSingletons() { System.out.println("[2] Eagerly built objects!"); }
}
}
主要方法将打印:
Created component.
Building all eager objects..
[1] Eagerly built objects!
[2] Eagerly built objects!
使用dagger multibindings可以解决。首先,您需要创建接口:
public interface EagerInit {
void eagerInit();
}
在 EagerModule
中,您将 EagerInit
实现绑定到设置中,因此您可以在 EagerComponent
:
中访问它
@Module
public abstract class EagerModule {
@Binds
@IntoSet
abstract EagerInit eagerInitImpl1(EagerInitImpl1 eagerInitImpl1);
@Binds
@IntoSet
abstract EagerInit eagerInitImpl2(EagerInitImpl2 eagerInitImpl2);
}
@Component(modules = {EagerModule.class})
public interface EagerComponent {
Set<EagerInit> getEagerInits();
}
创建 EagerComponent
后,您只需调用:
component.getEagerInits().forEach(EagerInit::eagerInit);
我在使用 Dagger 2 依赖项注入框架时遇到问题。我想创建一个 EagerSingleton。当我使用 @Singleton
注释时,我假设 dagger 2 创建了延迟加载的单例。如何使用 Dagger 2 框架创建 EagerSingleton?
我知道怎么做了:
根据 docs dagger 不直接支持 eagerSingletons 所以:
通过创建一个 EagerSingletons class 来解决这个问题,它为每个热切的单例声明静态字段。 方法注入.
所以我在任何我想使用急切单例的模块中创建了一个 EagerSingletons class。在那个 eagerSingletons class 中,我会声明我想使用的任何单例。就这样吧,dagger 然后让单身狗跃跃欲试。
更新:我以匕首 1 为例的原因是它在匕首 2 中是这样做的。确实没有针对 eagerSingleton 的机制。你必须使用静态字段来实现它。让我举例说明如何创建 eagerSingleton:
In every module you need a eager singleton you could have this:
//assume this file is called myModule.java
static EagerObjects eagerObjects;
public static void initEagerObjects() {
if (eagerObjects == null) {
eagerObjects = new EagerObjects();
}
}
//so far so good, only one object will be created, lets inject what we need immediately
public static class EagerObjects {
public EagerObjects() {
//inject right away,you'll have to figure out a way to pass the graph in. by constructor param should be fine
getGraph().inject(this);
}
//make this injection static
@Inject
static CoffeePot coffeePot;
}
}
现在想办法在应用程序启动时立即调用它....
回到你的匕首组件或你扩展的应用程序class你可以有一个静态方法来调用每个模块的每一个:
static void injectAllEagerObjects() {
myModule.initEagerObjects();
someOtherModule.initEagerObjects();
//...all of them can be here since there static
}
现在我们差不多完成了,只需在应用程序启动时调用它。 因此,在您从应用程序创建图形之后,您必须立即调用 injectAllEagerObjects() (如果需要,可能会在那里传递图形实例)。这将以正确的方式且仅初始化一次渴望的单例。
说了这么多,我希望 dagger 有一个你可以像这样使用的注释: @singleton(eager=true) 但静态字段,这是他们目前推荐的。
我通过创建一个 EagerModule
解决了这个问题,它有一个返回 Void
的单一提供方法。我急切地创建了所有我想要的东西,并将其指定为该方法的参数。然后我向组件添加了一个 Void init()
方法,我在创建组件后立即调用该方法。
@Module
public class EagerModule {
@Provides
@Nullable
Void provideEager(...) {
// this eagerly builds any parameters specified and returns nothing
return null;
}
}
@Component(modules = {EagerModule.class})
public interface TestComponent {
@Nullable
Void init();
}
这显然不会让您访问热切创建的单例,但对于我的使用,我不需要访问,我只是想创建它们。
这是我为 Dagger2 提出的可复制粘贴示例,我认为没有办法避免(冗余地)在组件中声明哪些模块具有急切对象。
如果有人能提供一个不那么样板的例子就好了。
Main.java
import dagger.Component;
import dagger.Module;
import dagger.Provides;
import javax.inject.Inject;
import javax.inject.Singleton;
public class Main {
public static void main(String[] args) {
TestComponent component = DaggerTestComponent.create();
System.out.println("Created component.");
component.createEagerSingletons();
}
}
@Component(modules = {TestModule1.class, TestModule2.class})
@Singleton
abstract class TestComponent {
abstract EagerSingletons createEagerSingletons();
static class EagerSingletons {
@Inject EagerSingletons() { System.out.println("Building all eager objects.."); }
@Inject TestModule1.EagerSingletons m1;
@Inject TestModule2.EagerSingletons m2;
}
}
@Module
class TestModule1 {
static class Thing1 { @Inject Thing1(){}}
static class Thing2 { @Inject Thing2(){}}
@Provides
@Singleton
Thing1 first() { return new Thing1(); }
@Provides
@Singleton
Thing2 secon() { return new Thing2(); }
static class EagerSingletons {
@Inject Thing1 a;
@Inject Thing2 b;
@Inject EagerSingletons() { System.out.println("[1] Eagerly built objects!"); }
}
}
@Module
class TestModule2 {
static class EagerSingletons {
@Inject EagerSingletons() { System.out.println("[2] Eagerly built objects!"); }
}
}
主要方法将打印:
Created component.
Building all eager objects..
[1] Eagerly built objects!
[2] Eagerly built objects!
使用dagger multibindings可以解决。首先,您需要创建接口:
public interface EagerInit {
void eagerInit();
}
在 EagerModule
中,您将 EagerInit
实现绑定到设置中,因此您可以在 EagerComponent
:
@Module
public abstract class EagerModule {
@Binds
@IntoSet
abstract EagerInit eagerInitImpl1(EagerInitImpl1 eagerInitImpl1);
@Binds
@IntoSet
abstract EagerInit eagerInitImpl2(EagerInitImpl2 eagerInitImpl2);
}
@Component(modules = {EagerModule.class})
public interface EagerComponent {
Set<EagerInit> getEagerInits();
}
创建 EagerComponent
后,您只需调用:
component.getEagerInits().forEach(EagerInit::eagerInit);