前言
ViewModelValidationPlugin用于校验@HiltViewModel注解和外部的关联。ViewModelProcessor类处理@HiltViewModel。当前使用该注解的节点校验并且生成ViewModelMetadata对象,针对该ViewModelMetadata对象再生成类。
ViewModelValidationPlugin
代码本身存在缺陷,所以做了简单处理,重点看
visitGraph(bindingGraph: BindingGraph, diagnosticReporter: DiagnosticReporter)方法即可。其他的不用管。
@HiltViewModel修饰的目的在于使用当前ViewModelProcessor创建ViewModel 实例;
现已一个案例来说明:
@Module
public class XXModule{
@Binds
@IntoMap
@StringKey(...)
@HiltViewModelMap
abstract ViewModel bindViewModel(FooViewModel vm)
}
以上bindViewModel方法的依赖匹配的是FooViewModel类使用@Inject修饰的构造函数,如下:
@HiltViewModel
class FooViewModel extends ViewModel{
@Inject
FooViewModel(){}
}
为了方便讲解,这里bindViewModel方法我们叫源头节点,该方法参数生成的依赖我们叫边,再把FooViewModel类使用@Inject修饰的构造函数我们称之为目标节点。
用于判断在某些情况下不允许使用@HiltViewModel的情况(即不能创建通过@HiltViewModel来创建ViewModule实例)。
如果目标节点是@Inject修饰的构造函数,并且该构造函数所在类使用了@HiltViewModel修饰,那么源头节点必须满足 :源头节点 必须是Binding对象(注释1) && 当前Binding对象的key使用@HiltViewModelMap注解修饰,并且当前Binding对象的key使用@IntoMap或@IntoSet或@ElementsIntoSet注解修饰;
注释1:可以自行查看Dagger关系图<component代码实现核心>哪些情况下可以生成Binding对象;
校验并且生成ViewModelMetadata对象
@HiltViewModel修饰的注解规则
-
使用@HiltViewModel修饰的节点必须继承androidx.lifecycle.ViewModel;
-
使用@HiltViewModel修饰的节点的构造函数不允许使用@AssistedInject,如果使用了@Inject修饰,那么有且仅有一个@Inject修饰的构造函数,并且该@Inject修饰的构造函数不允许使用private修饰;
-
@HiltViewModel修饰的节点如果是内部类,那么需要使用static修饰;
-
@HiltViewModel修饰的节点不允许使用@Scope修饰的注解修饰。
ViewModelMetadata对象对象属性
val typeElement: TypeElement - 就一个属性,当前@HiltViewModel修饰的节点。
ViewModelModuleGenerator生成类
demo如下
-
UserListViewModel
@HiltViewModel class UserListViewModel @Inject constructor( private val userListRepository: UserListRepository ) : ViewModel() {...} -
UserDetailsViewModel
@HiltViewModel class UserDetailsViewModel @Inject constructor( private val userDetailsRepository: UserDetailsRepository ) : ViewModel() {...}
@HiltViewModel修饰的节点生成的类
-
UserDetailsViewModel_HiltModules
@OriginatingElement( topLevelClass = UserDetailsViewModel.class ) public final class UserDetailsViewModel_HiltModules { private UserDetailsViewModel_HiltModules() { } @Module @InstallIn(ViewModelComponent.class) public abstract static class BindsModule { private BindsModule() { } @Binds @IntoMap @StringKey("com.aregyan.github.views.userDetails.UserDetailsViewModel") @HiltViewModelMap public abstract ViewModel binds(UserDetailsViewModel vm); } @Module @InstallIn(ActivityRetainedComponent.class) public static final class KeyModule { private KeyModule() { } @Provides @IntoSet @HiltViewModelMap.KeySet public static String provide() { return "com.aregyan.github.views.userDetails.UserDetailsViewModel"; } } } -
UserListViewModel_HiltModules
@OriginatingElement( topLevelClass = UserListViewModel.class ) public final class UserListViewModel_HiltModules { private UserListViewModel_HiltModules() { }
@Module @InstallIn(ViewModelComponent.class) public abstract static class BindsModule { private BindsModule() { }
@Binds @IntoMap @StringKey("com.aregyan.github.views.userList.UserListViewModel") @HiltViewModelMap public abstract ViewModel binds(UserListViewModel vm);}
@Module @InstallIn(ActivityRetainedComponent.class) public static final class KeyModule { private KeyModule() { }
@Provides @IntoSet @HiltViewModelMap.KeySet public static String provide() { return "com.aregyan.github.views.userList.UserListViewModel"; }} }
总结
@HiltViewModel修饰的节点生成的类包含static修饰的@Module类,该类使用@Binds、@IntoMap、@StringKey的目的是收集实例化的viewModule类。
至此hilt关于android模块已完成,下面是针对android或其他注解的进一步生成工作。