假设我有一个由Dagger 2创建的单例,该单例实现了接口Foo和Bar。代码中有使用的Foo地方,还有其他使用的地方Bar,但是无论注入哪个接口,我都希望使用相同的单例。这可能吗?
是的,这很容易做到,但也容易出错。诀窍是您需要小心制作@Singleton:Foo,Bar或FooBarImpl。
在Dagger中,任何特定的绑定都可以标记为Singleton,这就是Dagger干扰说“让我缓存此实例”的地方。像Foo和Bar这样的接口将在@Bindsor @Provides方法上对其进行标记,而像FooBarImpl这样的具体类将在@Provides方法或具有@Inject注释的实际类上对其进行标记。
@Singleton public class FooBarImpl implements Foo, Bar { /* ... */ }
// in your module:
@Binds Foo bindFoo(FooBarImpl impl);
@Binds Bar bindBar(FooBarImpl impl);
Run Code Online (Sandbox Code Playgroud)
这样,无论消费者要求Foo,Bar还是FooBarImpl,他们都将始终使用Dagger的内部双重检查锁定缓存实例(“ DoubleCheck”)。也可以标记Foo和Bar @Singleton,但这有点浪费,因为内部FooBarImpl提供程序总会始终返回相同的实例。无需在Foo Provider或Bar Provider上保留单独的副本。
如果FooBarImpl在控件的外部或外部,则可以@Singleton在@Provides方法上进行标记。
/* not Singleton */ public class FooBarImpl implements Foo, Bar { /* ... */ }
// in your module:
@Binds @Singleton Foo bindFoo(FooBarImpl impl);
@Binds Bar bindBar(Foo foo);
Run Code Online (Sandbox Code Playgroud)
假设Foo扩展了Bar,则可以将Bar绑定到Foo。在这里,单例实例保留在Foo提供程序中,注入FooBarImpl将返回新实例,并且Bar的注入每次都将咨询Foo(及其缓存提供程序)。
这听起来很严格糟糕,但也有有效的使用情况:试想一下,如果FooBarImpl是某种形式的CacheImpl,你想Foo和Bar一个实例,但返回@Named("accounts") ListeningCache,并@Named("accounts") Cache于都返回相同的不同实例。
为了完整性:
/* not Singleton */ public class FooBarImpl implements Foo, Bar { /* ... */ }
// in your module:
@Binds @Singleton Foo bindFoo(FooBarImpl impl);
@Binds @Singleton Bar bindBar(FooBarImpl impl);
Run Code Online (Sandbox Code Playgroud)
在这里,Foo和Bar将各自返回一个单独的Singleton实例,并且注入FooBarImpl每次将返回一个新实例。这对于需要两个或多个对象的用例非常有用,但是在尝试实现上面的“不太理想”的解决方案时,请小心不要意外地实现此解决方案。它们看起来确实很相似,但是行为却截然不同。
| 归档时间: |
|
| 查看次数: |
690 次 |
| 最近记录: |