前言
Dagger2当前版本有android和compiler、hilt三个板块。这里对android板块下的注解解说,该板块下主要针对@AndroidInjectionKey和@ClassKey两个注解、@ContributesAndroidInjector注解的处理。
换句话说如果项目中不存在使用AndroidInjectionKey、ClassKey和ContributesAndroidInjector注解,不要轻易将当前android板块引入到项目中。
@AndroidInjectionKey 和 @ClassKey
@AndroidInjectionKey和@ClassKey本身就是使用@MapKey注解修饰的注解。
先回一下@MapKey注解规则:
- 如果MapKey.unwrapValue() = true的情况下(默认情况下就是true),被修饰的注解有且仅有一个方法,并且该方法返回类型不能是数组类型;
- e.g.ClassKey注解
- 如果MapKey.unwrapValue() = false,那就麻烦了,被修饰的注解方法不但不限制,而且我们的项目中必须引入了
com.google.auto.value.AutoAnnotation
依赖,这是什么骚操作???
-
(1)引入AutoAnnotation的目的是对MapKey修饰的注解的所有方法返回类型作为变量生成一个新的类T,相当于MapKey.unwrapValue() = true的情况下的
@MapKey(T.class)
; -
(2)所以
MapKey.unwrapValue() = false
可以使用MapKey.unwrapValue() = true
替代,而且MapKey.unwrapValue() = true
更容易理解、实现也更加稳健。非必要不要使用MapKey.unwrapValue() = false
;
- @MapKey修饰的注解和@IntoMap是情侣关系,必须在一起!!!
AndroidInjectionKey注解只能修饰方法,ClassKey注解可以修饰方法和变量。
我们仅仅针对@AndroidInjectionKey或@ClassKey修饰的方法做校验工作,校验规则如下:
-
@AndroidInjectionKey 和 @ClassKey 必须满足@MapKey注解规则;
-
如果方法使用了@AndroidInjectionKey或@ClassKey修饰,那么当前方法不能使用@Qualifier修饰的注解修饰;
-
使用@AndroidInjectionKey或@ClassKey修饰修饰的方法返回类型如果不是AndroidInjector.Factory及其子类,不需要继续校验了,该方法直接被忽略;
-
如果该方法使用了@Scope注解修饰的注解修饰,该方法必须使用@SuppressWarnings注解修饰,并且该@SuppressWarning注解包含dagger.android.ScopedInjectorFactory值;
-
方法返回类型必须是AndroidInjector.Factory类型;
-
如果方法使用了@Binds修饰并且方法参数有且仅有一个,当前方法参数类型必须是AndroidInjector.Factory的子类,这里的T表示@AndroidInjectionKey或@ClassKey注解的方法类型,如下案例:
@Binds @IntoMap @ClassKey(GreenActivity.class) abstract AndroidInjector.Factory<?> bindBlueActivity( BlueActivityComponent.Builder builder); } 复制代码
BlueActivityComponent.Builder是AndroidInjector.Factory< GreenActivity>子类
@ContributesAndroidInjector
@ContributesAndroidInjector注解用于修饰方法。
@ContributesAndroidInjector修饰的方法校验规则如下:
-
方法必须使用abstract修饰(按理说修饰的是接口方法也ok);
-
方法不能有参数;
-
方法的父级类必须是@Module修饰的module节点;
-
该方法的返回类型不能使用泛型;
-
@ContributesAndroidInjector#modules里面的节点必须使用@Module注解;
-
该方法不能使用@Qualifier修饰的注解修饰;
我们以下面的案例来说下@ContributesAndroidInjector修饰的方法的作用:
@Module
abstract class MainActivityModule {
@ContributesAndroidInjector(modules = [FragmentBuildersModule::class])
abstract fun contributeMainActivity(): MainActivity
}
复制代码
通过Dagger的android模块生成如下代码:
@Module(subcomponents = MainActivityModule_ContributeMainActivity.MainActivitySubcomponent.class)
public abstract class MainActivityModule_ContributeMainActivity {
private MainActivityModule_ContributeMainActivity() {}
@Binds
@IntoMap
@ActivityKey(MainActivity.class)
abstract AndroidInjector.Factory<? extends Activity> bindAndroidInjectorFactory(
MainActivitySubcomponent.Builder builder);
@Subcomponent(modules = FragmentBuildersModule.class)
public interface MainActivitySubcomponent extends AndroidInjector<MainActivity> {
@Subcomponent.Builder
abstract class Builder extends AndroidInjector.Builder<MainActivity> {}
}
}
复制代码
这里表示的是当前bindAndroidInjectorFactory的返回类型匹配上参数类型。那么bindAndroidInjectorFactory方法在哪里被收集?如下:
@Module
public abstract class AndroidInjectionModule {
@Multibinds
abstract Map<Class<? extends Activity>, AndroidInjector.Factory<? extends Activity>>
activityInjectorFactories();
...
}
复制代码
bindAndroidInjectorFactory方法被AndroidInjectionModule类的activityInjectorFactories方法收集。
@ContributesAndroidInjector修饰的方法生成业务代码规则:
-
生成的module类名命名规则:@ContributesAndroidInjector修饰的方法所在module节点(如果module节点是内部类,外部”“拼接当前module节点) + “” +当前方法首字母大写后的名称;
-
生成module类的内部类规则:@ContributesAndroidInjector修饰的方法的返回类型 + “Subcomponent”生成一个subcomponent接口,;再生成一个Factory抽象类作为subcomponent的内部类;
-
module类添加@Module(subcomponents=module.subcomponent.class)注解,并且使用
public abstract
修饰,并且添加一个private无参构造函数; -
添加
bindAndroidInjectorFactory
方法:
-
(1)方法名:bindAndroidInjectorFactory,abstract修饰;
-
(2)使用@Binds和@IntoMap注解修饰,并且使用@ClassKey(T.class)或@AndroidInjectionKey(T.class)修饰,T表示@ContributesAndroidInjector修饰的方法返回类型;
-
(3)返回类型是AndroidInjector.Factory<? extends T的父级类>;
-
(4)参数名是builder,参数类型是subcomponent.Factory;
- 生成的subcomponent接口规则:
-
(1)添加@Subcomponent注解;如果当前@ContributesAndroidInjector注解中包含modules值,那么subcomponent接口添加注解格式如下:@Subcomponent(modules = @ContributesAndroidInjector注解中包含modules值);
-
(2)生成的subcomponent是一个
public
修饰接口,如果@ContributesAndroidInjector注解的方法中使用了@Scope修饰的注解,那么当前subcomponent接口沿用该@Scope修饰的注解; -
(3)subcomponent接口继承AndroidInjector< T>,T表示@ContributesAndroidInjector修饰的方法返回类型;
-
(4)subcomponent接口中添加Factory接口(如果是Builder,生成Builder抽象类,那么添加@Subcomponent.Builder注解,继承AndroidInjector.Builder< T>):
-
① 接口名称是Factory,使用
public static
修饰,添加@Subcomponent.Factory注解; -
②Factory接口继承AndroidInjector.Factory< T>,T表示@ContributesAndroidInjector修饰的方法返回类型。
总结
当前@ContributesAndroidInjector修饰的方法生成的module类和相关方法在component还需要进行二次处理,自行往后看!
可在QQ群:575306647 讨论