上一期介绍了Dagger是如何应对多个同类型变量的,这一期主要介绍,在对原对象不做任何修改的情况下如何将其注入。
主体代码
现在将ClassA
的所有标注全都去掉:
public class ClassA {
private int a;
private int b;
public ClassA(int a, int b) {
this.a = a;
this.b = b;
}
public int getA() {
return a;
}
public int getB() {
return b;
}
}
好了,那么现在Dagger要从哪里知道ClassA
的构造函数以及参数呢?
答案是在Module
里。现在Dagger自己无法查到ClassA
的带@Inject
标注的构造器了,于是转而要Module @Provides
一个出来,具体如下:
@Module
public class ModuleA {
private int a;
private int b;
public ModuleA(int a, int b) {
this.a = a;
this.b = b;
}
@Provides
@Named("a")
int provideIntA() {
return a;
}
@Provides
@Named("b")
int provideIntB() {
return b;
}
@Provides
ClassA provideClassA(@Named("a") int a, @Named("b") int b) {
return new ClassA(a, b);
}
}
是不是和原来的ClassA
的构造器很像?更神奇的一点是,Dagger会自动搜索所需参数,然后在这里找@Provides
同类型参数的函数,同样多个同类型的参数可以用@Named
来解决。
当然也可以不必这么麻烦,可以在构造ModuleA
的时候new一个ClassA
出来,到时候返回去。可见Dagger也是很有自由发挥空间的,只要把握几个要点就可以了。
比如说Dagger生成的DaggerComponent其实可以不急于inject,而是需要的时候再inject。常见的就是在App初始化的时候生成一堆之后可能需要的DaggerComponent,然后等哪个地方需要就获取然后再注入。
MainActivity
与ClassAComponent
并没有什么变化。
生成代码
生成代码没有太多变化,除了ClassA
原来的构造器Dagger不知道了,现在用ModuleA_ProvideClassAFactory
来代替:
public final class ModuleA_ProvideClassAFactory implements Factory<ClassA> {
private final ModuleA module;
private final Provider<Integer> aProvider;
private final Provider<Integer> bProvider;
public ModuleA_ProvideClassAFactory(
ModuleA module, Provider<Integer> aProvider, Provider<Integer> bProvider) {
assert module != null;
this.module = module;
assert aProvider != null;
this.aProvider = aProvider;
assert bProvider != null;
this.bProvider = bProvider;
}
@Override
public ClassA get() {
return Preconditions.checkNotNull(
module.provideClassA(aProvider.get(), bProvider.get()),
"Cannot return null from a non-@Nullable @Provides method");
}
public static Factory<ClassA> create(
ModuleA module, Provider<Integer> aProvider, Provider<Integer> bProvider) {
return new ModuleA_ProvideClassAFactory(module, aProvider, bProvider);
}
/** Proxies {@link ModuleA#provideClassA(int, int)}. */
public static ClassA proxyProvideClassA(ModuleA instance, int a, int b) {
return instance.provideClassA(a, b);
}
}
生成的代码确实是“一个模子”里出来的。
这里体现出封装的好处了:在无法直接调用构造器的情况下,使用Provider
接口封装之后其余代码几乎没有什么区别。
到目前为止,我们看到的只是很简单的依赖关系,那么交叉依赖又如何?例如ClassB
需要ClassA
与另一个整数a,而ClassA
又依赖于a
?Dagger是提供了很多方法来解决的,我们拭目以待吧。