我刚刚测试了 Dagger 2,并且在单例注释方面出现了一些奇怪的行为。我创建了一些测试代码来显示我的问题。
我的模块:
@Module
public class App {
@Provides
@Singleton
ThingA provideThingA(){
return new ConcreteThingA();
}
}
我想要的单例接口:
public interface ThingA {
void showMyId();
}
执行:
public class ConcreteThingA implements ThingA {
@Override
public void showMyId() {
System.out.println(this);
}
}
执行Dagger的代码:
public void doStuff() {
ThingA thingA=DaggerThingAComponent.create().provideThingA();
ThingA thingB=DaggerThingAComponent.create().provideThingA();
System.out.println("Hello");
}
这是一个屏幕截图,显示当我请求两次时我没有得到相同的实例。我是否错过了一些基本的东西? ThingA 只是一个愚蠢的名字,在我的实际应用程序中,我希望在我的服务上有这种单例行为。
诀窍在于 Dagger 通过组件强制执行范围/生命周期,并且您在此处创建了两个单独的组件:
ThingA thingA = DaggerThingAComponent.create().provideThingA();
ThingA thingB = DaggerThingAComponent.create().provideThingA();
每次创建新的顶级 @Singleton 注解组件时,Dagger 都会为每个 @Singleton 对象创建一个全新的对象图,其中包含一个全新的容器。你应该用这个代替:
ThingAComponent component = DaggerThingAComponent.create();
ThingA thingA = component.provideThingA();
ThingA thingB = component.provideThingA(); // thingA == thingB
当然,通过依赖关系图进一步访问的任何内容都来自同一组件,因此这将保留您正在寻找的单例行为。
在大多数情况下,您不需要传递组件:组件应该用于顶级组件,并且通过注入器可访问的任何内容都应该@Inject其依赖项(这意味着它不需要对组件本身的引用) )。在迁移到 DI 或 Dagger 期间这可能会出现问题,但创建多个 @Singleton 组件并不是解决这个问题的方法。相反,请尝试以下操作之一:
- 如果您需要某物的多个实例,您可以随时注入
Provider<T>
代替T
无论您是否创建了@Provides
方法。为此,您可以注入一个Lazy<T>
如果您只需要特定依赖项的零个或一个副本,特别是如果该对象的创建特别繁重。
- 如果您需要在对象图深处需要它,您可以 @Inject 组件本身,尽管它总是更好
@Inject Provider<T> tProvider
代替@Inject YourComponent
只是打电话YourComponent.getT
.
- 在某些情况下,包括 Android,将组件保存到全局可访问的字段可能是有意义的,可以作为应用程序中的实例字段,也可以作为其他位置的静态字段。这具体是因为 Android 自己反射性地创建对象,而不是从图中获取注入的实例。对于所有其他情况,请注入依赖项以避免需要传递组件。
也可以看看:图中的绑定来自 Dagger 2 用户指南
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)