使用Google Guice或Gin我可以指定参数不受依赖注入框架控制:
class SomeEditor {
@Inject
public SomeEditor(SomeClassA a, @Assisted("stage") SomeClassB b) {
}
}
辅助参数stage
在创建SomeEditor
实例时指定。
SomeClassA的实例取自对象图,SomeClassB的实例在运行时从调用者获取。
在Dagger中有类似的方法吗?
因为工厂是一种独立的样板来优化(see mailing list discussion here),Dagger把它留给了姐妹项目AutoFactory。这提供了Guice通过assisted injection提供的“FactoryModuleBuilder”功能,但有一些额外的好处:
例如,从AutoFactory的README中提取,它将在SomeClassFactory
注释的构造函数中生成providedDepA
,@Inject
和depB
方法生成create
:
@AutoFactory
final class SomeClass {
private final String providedDepA;
private final String depB;
SomeClass(@Provided @AQualifier String providedDepA, String depB) {
this.providedDepA = providedDepA;
this.depB = depB;
}
// …
}
是的,请查看这个Square项目:square/AssistedInject
目前它尚未达到1.0的目的。他们等到Dagger将引入一个公共API来自动注册那些生成的Module
类 - 请参阅this issue。有了这个,你就不必在你的Dagger代码中引用它们,如README中的这个例子:
@AssistedModule
@Module(includes = AssistedInject_PresenterModule.class)
abstract class PresenterModule {}
就像@xsveda一样,我也写了一个关于这个in this other question的答案,我也会在这里重现。
今天,对于Dagger的辅助注射,你可能想要使用AssistedInject。我在this blogpost上写过它,但我会在这里添加一个完整的例子以使事情变得更容易。
你需要的第一件事是依赖:
compileOnly 'com.squareup.inject:assisted-inject-annotations-dagger2:0.4.0'
kapt 'com.squareup.inject:assisted-inject-processor-dagger2:0.4.0'
然后这是它的样子:
class ImageDownloader @AssistedInject constructor(
private val httpClient: HttpClient,
private val executorService: ExecutorService,
@Assisted private val imageUrl: URL,
@Assisted private val callback: ImageCallback
) {
@AssistedInject.Factory
interface Factory {
fun create(imageUrl: URL, callback: ImageCallback): ImageDownloader
}
}
首先,不是用@Inject
注释构造函数,而是用@AssistedInject
注释它。然后我们注释必须通过工厂的参数,这与AutoFactory所期望的相反。最后,我们需要一个用@AssistedInject.Factory
注释的内部工厂接口,它有一个接收辅助参数的方法并返回我们感兴趣的实例。
不幸的是,我们还有一个额外的步骤:
@AssistedModule
@Module(includes = [AssistedInject_AssistedInjectModule::class])
interface AssistedInjectModule
我们不一定需要专门的模块,即使这是一个有效的选项。但是我们也可以在已经安装在组件中的另一个模块中添加这些注释。这里的好处是我们只需要做一次,之后任何工厂都会自动成为图形的一部分。
有了它,您基本上可以像平常一样注入工厂并询问您的对象。