前言
当前主要针对@Inject、@AssistedInject、@Assisted、@AssistedFactory注解解说。@AssistedInject、@Assisted和@AssistedFactory三个是Dagger新出现的注解,在一起使用。@Inject主要是用于修饰构造函数、变量和普通方法。
@Inject、@AssistedInject、@Assisted、@AssistedFactory注解
所有使用Dagger注解,建议都不可以使用private修饰,最好使用public修饰,这是铁律。
@Inject和@AssistedInject修饰构造函数
@Inject和@AssistedInject修饰构造函数规则:
-
节点的构造函数不允许同时使用Inject注解和AssistedInject注解;
-
@Inject、@AssistedInject都可以用来修饰构造函数,并且该构造函数不允许使用private修饰,也不能被@Qualifier修饰的注解修饰;
-
被Inject或AssistedInject修饰的构造函数不能被@Scope注解修饰的注解修饰;
-
@Inject或@AssistedInject修饰的构造函数的参数不能是Produced< T>和Producer< T>类型,参数表示依赖,下面有所有依赖来源,以及依赖校验,这里不对赘述;
-
被@Inject或@AssistedInject修饰的构造函数如果throws异常,那么异常一定要是RuntimeException或Error或两者子类;
-
使用了@Inject或@AssistedInject修饰的构造函数所在父节点不可以被private类使用,该构造函数所在父节点也不能使用abstract修饰,并且如果构造函数所在父节点是一个内部类,那么该内部类必须使用static修饰;
-
一个类最多只能有一个构造函数被@Inject或@AssitedInject修饰;
-
使用@AssistedInject修饰的构造函数所在的父节点不能被使用@Scope注解修饰的注解修饰;
@Inject修饰变量或普通方法
@Inject修饰变量类型或普通方法的参数类型作为依赖,需要做依赖校验,自行查看下面的依赖校验,我们这里对@Inject修饰变量类型或普通方法进行校验:
-
@Inject修饰的变量节点不能使用final修饰;也不要使用private和static修饰(可能警告可能报错;
-
@Inject修饰的普通方法必须是实现类,不能是abstract修饰的抽象类或接口方法;
-
@Inject修饰的普通方法不要使用private和static修饰(可能报错可能警告);
-
@Inject修饰的普通方法不能使用泛型类型,并且不能throws异常;
-
Inject修饰的节点所在父节点最好不要被private修饰(可能警告可能报错);并且Inject修饰的节点所在父节点不能是Kotlin Object或Kotlin Companion Object对象;
@AssistedInject、@Assisted和@AssistedFactory在一起!!!
@AssistedInject仅仅用于修饰构造函数,规则上面已经说了,自行查看。
Assisted修饰的节点规则如下:
- Assisted只能修饰方法参数,并且仅仅满足以下条件:
-
(1)@Assisted修饰的参数,位于一个被@AssistedInject修饰的构造函数中;
-
(2)@Assisted修饰的参数所在的方法节点是所在父节点中唯一的一个abstract、非static、非private修饰的方法;
-
(3)@Assisted修饰的参数所在的方法 ,如果该方法命名包含"copy" ,那么该方法所在类是一个data类型的kotlin文件;
-
@Assisted修饰的参数节点不能被Qualifier注解修饰的注解修饰;
-
@AssistedInject修饰的构造函数或@AssistedFactory修饰的节点中的普通方法都不允许出现重复的@Assisted修饰的参数类型。
AssistedFactory修饰的节点中的方法仅仅针对abstract(接口除外)、非static、非private修饰的方法校验,AssistedFactory注解使用规则如下:
-
使用@AssistedFactory修饰的节点仅仅支持抽象类或接口;
-
如果@AssistedFactory修饰的节点是内部类,那么必须使用static修饰;
-
@AssistedFactory修饰的节点必须有且仅有一个abstract、非static、非private的方法节点;
-
@AssistedFactory修饰的节点中的方法返回类型的构造函数必须使用@AssistedInject修饰;
-
@AssistedFactory修饰的节点中的方法不允许使用泛型;
-
@AssistedFactory修饰的节点中的唯一方法传递的参数 和 该方法返回类型中的构造函数使用@Assisted注解修饰的参数 保持一致。
依赖校验
这里面有一个依赖校验的概念,依赖类型有(1)@Inject修饰的变量类型、(2)@Inject修饰的普通方法或构造函数参数类型;(3)@AssistedInject修饰的构造函数排除@Assisted修饰的其他参数类型、(4)component节点中存在的无参方法的返回类型;(5)bindingMethod方法参数类型;
component节点表示使用@Component、@Subcomponent、@ProductionComponent、@ProductionSubcomponent注解的节点; bindingMethod方法,表示使用@Provides、@Produces和@Binds的方法参数(@BindsOptionalOf和@Multibindings修饰的bindingMethod方法是没有参数的);
校验规则如下:
-
依赖节点不能使用通配符;
-
依赖节点是MembersInjector< T>(必须存在T)类型,对T表示的类不能使用Qualifier注解修饰的注解修饰;
- 如果依赖节点是MembersInjector< T>(必须存在T)类型,收集当前T表示的类中使用@Inject修饰的变量或普通方法对其实现实例化。但是!!!个人建议别这么骚操作,最大的不确定性就是实例化过程的参数依赖是否能匹配到;
- 还有一些其他细的规则,想了解可以自己去骚操作一番!!!自行看提示!
案例
以一个案例的形式彻底说明以上三个注解,还外送其他注解!!!
1.ComponentProcessor类对XProcessingStep变量实例化:
public class ComponentProcessor {
@Inject
XProcessingStep processingStep;
}
2.XProcessingStep作为依赖匹配到ProcessingStepsModule的processingSteps方法:
@Module
interface ProcessingStepsModule {
@Provides
static XProcessingStep processingSteps(
ComponentProcessingStep componentProcessingStep
) {
return componentProcessingStep;
}
//processingSteps或者这么写
@Binds
XProcessingStep processingSteps(ComponentProcessingStep componentProcessingStep);
}
3. ComponentProcessingStep作为依赖匹配到ComponentProcessingStep类使用@Inject修饰的构造函数;
final class ComponentProcessingStep extends XProcessingStep {
@Inject
ComponentProcessingStep(
ComponentRequestRepresentations componentRequestRepresentations) {
this.componentRequestRepresentations = componentRequestRepresentations;
}
}
4. ComponentProcessingStep类使用@Inject修饰的构造函数的参数作为依赖匹配到ComponentRequestRepresentations使用Inject修饰的构造函数:
public final class ComponentRequestRepresentations {
@Inject
ComponentRequestRepresentations(
LegacyBindingRepresentation.Factory legacyBindingRepresentationFactory) {
this.legacyBindingRepresentationFactory = legacyBindingRepresentationFactory;
LegacyBindingRepresentation legacyBindingRepresentation = legacyBindingRepresentationFactory.create(true,new Binding(),new SwitchingProviders());
}
}
5. LegacyBindingRepresentation.Factory匹配到LegacyBindingRepresentation类中@AssistedFactory修饰的Factory接口,并且该接口的create方法的返回类型匹配到@AssistedInject修饰的LegacyBindingRepresentation构造函数,创建LegacyBindingRepresentation对象是@Assisted修饰的参数通过Factory接口create方法传递进入;
final class LegacyBindingRepresentation{
@AssistedInject
LegacyBindingRepresentation(
@Assisted boolean isFastInit,
@Assisted Binding binding,
@Assisted SwitchingProviders switchingProviders,
...) {
}
@AssistedFactory
static interface Factory {
LegacyBindingRepresentation create(
boolean isFastInit,
Binding binding,
SwitchingProviders switchingProviders
);
}
}
6. 必须有一个承载ComponentProcessor类中@Inject修饰变量实例化的容器,并且ComponentProcessor类中@Inject修饰变量实例化的匹配(1)要么是@Inject修饰的构造函数;(2)要么必须是容器关联到的绑定,e.g.ProcessingStepsModule的processingSteps方法
@Component(
modules = {
ProcessingStepsModule.class//关联
}
)
interface ProcessorComponent {
//表示当前容器注入ComponentProcessor中使用@Inject修饰的变量实例对象
void inject(ComponentProcessor processor);
static Factory factory() {
return DaggerComponentProcessor_ProcessorComponent.factory();
}
@Component.Factory
interface Factory {
@CheckReturnValue
ProcessorComponent create();
}
}
总结
以上说的我感觉挺爽的,也感觉抓到了重点。如果有不完善或者不足之处欢迎指正!!!
可在QQ群:575306647 讨论