使用Dagger

时间:2017-09-29 21:16:10

标签: dagger-2

假设我有一个由Dagger 2创建的单例,它实现了接口FooBar。代码中有些地方使用Foo,其他地方使用Bar,但无论注入哪个接口,我都想要相同的单例。这可能吗?

2 个答案:

答案 0 :(得分:4)

是的,这很容易做到,但也很容易做错。诀窍是你需要小心你@Singleton:Foo,Bar或FooBarImpl。

在Dagger中,任何特定的绑定都可以标记为Singleton,而Dagger干扰的地方是"让我缓存此实例"。像Foo和Bar这样的接口会在@Binds@Provides方法上标记它,像FooBarImpl这样的具体类会在@Provides方法或具有{的实际类上标记它{1}}注释。

理想:标记你的实现@Singleton

@Inject

这样,无论消费者要求Foo,Bar还是FooBarImpl,他们总是会去Dagger的内部双重检查锁定缓存实例(" DoubleCheck") 。 Foo和Bar也可以标记为@Singleton public class FooBarImpl implements Foo, Bar { /* ... */ } // in your module: @Binds Foo bindFoo(FooBarImpl impl); @Binds Bar bindBar(FooBarImpl impl); ,但它有点浪费,因为内部FooBarImpl提供程序总是会返回相同的实例。无需在Foo Provider或Bar Provider上保留单独的副本。

如果FooBarImpl在外部或在您的控制之外,您可以在@Singleton方法上标记@Singleton

不太理想:标记一个并将另一个绑定到它

@Provides

假设Foo扩展了Bar,你可以将Bar绑定到Foo。在这里,单例实例保存在Foo提供程序中,注入FooBarImpl将返回新实例,并且Bar的注入将每次都咨询Foo(及其缓存提供程序)。

这听起来严重得多,但是有一些有效的用例:想象一下,如果FooBarImpl是某种类型的CacheImpl,并且你希望Foo和Bar返回一个实例,只有/* not Singleton */ public class FooBarImpl implements Foo, Bar { /* ... */ } // in your module: @Binds @Singleton Foo bindFoo(FooBarImpl impl); @Binds Bar bindBar(Foo foo); @Named("accounts") ListeningCache返回相同的不同实例。

不是你想要的:单独的单例绑定

为了完整性:

@Named("accounts") Cache

在这里,Foo和Bar将各自返回一个单独的Singleton实例,并且每次注入FooBarImpl将返回一个新实例。这对于您需要两个或更多对象的用例非常有用,但是当您尝试实现“不太理想”时,请注意不要意外地实施此解决方案。解决方案如上它们看起来非常相似,但行为却截然不同。

答案 1 :(得分:0)

interface FooBar extends Foo, Bar

class FooBarImpl implements FooBar {...}

@SomeScope @Binds FooBar bindsFooBar(impl: FooBarImpl)
@SomeScope @Binds Foo bindsFoo(fooBar: FooBar)
@SomeScope @Binds Bar bindsBar(fooBar: FooBar)