前言
BindValueProcessor
类处理@BindValue、@BindValueIntoSet、@BindElementsIntoSet或@BindValueIntoMap。当前使用该注解的节点校验并且生成BindValueMetadata
对象,针对该BindValueMetadata
对象再生成类。
@BindValue、@BindValueIntoSet、@BindElementsIntoSet或@BindValueIntoMap修饰变量,这些注解的作用是用于测试。并且这些注解修饰的变量必须存在于@HiltAndroidTest修饰的类中。
校验并且生成BindValueMetadata对象
@BindValue、@BindValueIntoSet、@BindElementsIntoSet或@BindValueIntoMap修饰的bindValue节点变量校验规则如下:
-
@BindValue、@BindValueIntoSet、@BindElementsIntoSet或@BindValueIntoMap同一个变量上只能被其中一个修饰;
-
bindValue节点只能是变量;
-
bindValue节点所在父节点如果是类或接口,并且是kotlin文件,那么bindValue节点的getter方法不能使用private修饰;表示kotlin文件,那么当前bindValue变量不能使用private修饰;
-
bindValue变量不能使用@Inject注解修饰;
-
bindValue变量上最多只能使用一个@Qualifier修饰的注解修饰;
-
bindValue变量如果使用了@BindValueIntoMap修饰,那么必须和@MapKey修饰的注解必须同时使用,并且@MapKey修饰的注解只允许出现一次;
-
bindValue变量不允许使用@Scope修饰的注解修饰;
-
bindValue变量所在类必须使用@HiltAndroidTest注解修饰;
-
bindValue变量如果使用@BindElementsIntoSet修饰则当前变量必须是Set< T> - 源码中没有体现,这条是根据@ElementsIntoSet规则推理出来的。
以上可知,bindingValue变量的作用是做测试。
BindValueMetadata对象属性
-
TypeElement testElement:bindingValue节点所在类;
-
ImmutableSet bindValueElements:bindingValue节点所在类的所有bindingValue节点,查看BindValueElement对象;
BindValueElement对象属性
bindingValue节点所在类的所有bindingValue节点。具体属性如下:
- VariableElement variableElement:bindingValue变量;
- ClassName annotationName:bindingValue变量使用的@BindValue、@BindValueIntoSet、@BindElementsIntoSet或@BindValueIntoMap注解类名,
- Optional qualifier:bindingValue变量使用的@Qualifier修饰的注解,
- Optional mapKeybindingValue变量使用的@MapKey修饰的注解,
- Optional getterElement:用于获取当前bindingValue变量的getter方法。
BindValueGenerator生成类
demo:
@HiltAndroidTest
public class FooTest{
@BindValue
Bar bar;
@BindValueIntoSet
BarIntoSet barIntoSet;
@BindElementsIntoSet
Set<BarElementsIntoSet> barElementsIntoSet;
@BindValueIntoMap
@ClassKey(Foo.class)
BarIntoMap barIntoMap;
}
生成的代码:
@Module
@OriginatingElement(topLevelClass = FooTest.class)
@InstallIn(SingletonComponent.class)
@Generated("BindValueGenerator")
public final class FooTest_BindValueModule {
@Provides
static FooTest providesFooTest(@ApplicationContext Context context) {
return (FooTest)
((TestApplicationComponentManager)
((TestApplicationComponentManagerHolder) context).componentManager())
.getTestInstance();
}
@Provides
static Bar providesBar(FooTest test) {
return test.bar;
}
@IntoSet
@Provides
static BarIntoSet providesBarIntoSet(FooTest test) {
return test.barIntoSet;
}
@ElementsIntoSet
@Provides
static Set<BarElementsIntoSet> providesSet(FooTest test) {
return test.barElementsIntoSet;
}
@IntoMap
@ClassKey(Foo.class)
@Provides
static BarIntoMap providesBarIntoMap(FooTest test) {
return test.barIntoMap;
}
}
总结
bindvalue节点实际起到的是测试的作用,将bindvalue节点转换成一个@Module和@InstallIn(SingletonComponent.class)共同修饰的module节点里面的一个bindingMethod方法,以待做下一步处理。