Dagger负责创建工厂,帮忙生产instance
1. SetPasswordActivityComponent 桥梁的作用: 将带有 @Inject 的方法或对象和带有 @Module 的类进行关联
2. SetPasswordBindsModule 绑定 4 ViewModel创建工厂到map集合
3. SetPasswordModule 提供 4 ViewModel实例
4. SetPasswordViewModel 感知生命周期的方式存储和管理 UI 相关数据,ViewModel中数据会一直存活即使 activity configuration发生变化,比如横竖屏切换的时候。
5.SetPasswordPresenter 逻辑部分 供 4 SetPasswordViewModel 调用
6.SetPasswordActivity dagger编译后,初始化相关,调用 ViewModel 相关方法
DaggerSetPasswordActivityComponent SetPasswordActivity_MembersInjector SetPasswordModule_ProvideViewModelFactory SetPasswordPresenter_Factory SetPasswordViewModel_Factory_Factory
注意点:
@Inject注解在构造函数上时,会根据被注解的构造函数生成该类的工厂类@Inject注解在变量和方法上时,表示这些变量和方法需要被注入,会生成相应的注入器 class CPU @Inject constructor() { /* ... */ } class Memory @Inject constructor(private val size: Int) { /* ... */ }dagger对于有@Inject注解的构造函数的类,会根据被注解的构造函数生成一个实现了Factory接口的工厂类
注解在变量和方法上
@Inject lateinit var viewModel: SetPasswordViewModel编译后可以发现dagger又生成了新的类 SetPasswordActivity_MembersInjector
SetPasswordActivityComponent
@ModuleScope @Component( modules = [ AndroidInjectionModule::class, AccountModule::class, SetPasswordModule::class, SetPasswordBindsModule::class ], dependencies = [CoreComponent::class] ) interface SetPasswordActivityComponent : AndroidInjector<SetPasswordActivity> { @Component.Builder abstract class Builder : AndroidInjector.Builder<SetPasswordActivity>() { /** * 引入和核心组件. * @param coreComponent CoreComponent * @return Builder */ abstract fun coreComponent(coreComponent: CoreComponent): Builder } }SetPasswordBindsModule
@Module abstract class SetPasswordBindsModule { /** * 绑定ViewModel创建工厂到map集合. * @param factory SetPasswordViewModel.Factory SetPasswordViewModel_AssistedFactory实例. * @return ViewModelAssistedFactory<out ViewModel> */ @Binds @IntoMap @ViewModelKey(SetPasswordViewModel::class) abstract fun bindFactory(factory: SetPasswordViewModel.Factory): ViewModelAssistedFactory<out ViewModel> }SetPasswordModule
@Module class SetPasswordModule { /** * 提供ViewModel实例. * @param viewModelMap MutableMap<Class<out ViewModel>, ViewModelAssistedFactory<out ViewModel>> * @param activity SetPasswordActivity * @return SetPasswordViewModel */ @Provides fun provideViewModel( viewModelMap: MutableMap<Class<out ViewModel>, ViewModelAssistedFactory<out ViewModel>>, activity: SetPasswordActivity ): SetPasswordViewModel = ViewModelProviders.of(activity, ViewModelFactory(viewModelMap, activity, null)).get(SetPasswordViewModel::class.java) }SetPasswordViewModel
class SetPasswordViewModel( private val setPasswordPresenter: SetPasswordPresenter, private val accountDataManager: AccountDataManager ) : CoreViewModel() { val accountDataService: AccountDataService? = getAService<AccountDataService>() val canInvite = accountDataService?.userInfo?.value?.canInvite ?: false /** * 设置密码. * @param password String * @return Job */ fun setPassword(password: String, inviteCode: String?) = launch { // 校验密码是否符合格式. _loadingState.value = LoadState.Loading setPasswordPresenter.setPassword(password, inviteCode) .onSuccess { accountDataManager.updatePasswordState() accountDataService?.getToastContent() _loadingState.value = LoadState.Loaded() }.onFailure { if (it is Response.Exception && (it.response.code == ServerCodes.BEHAVIOR_VERIFICATION_CODE || it.response.code == ServerCodes.BEHAVIOR_VERIFICATION_CODE_TWO) ) { _loadingState.value = LoadState.LoadError( Response.Exception( Response( ServerCodes.BEHAVIOR_VERIFICATION_CODE_TWO, "", " " ) ) ) refreshVerifyCode(password, inviteCode) } else { _loadingState.value = LoadState.LoadError(it) } } } /** * 刷新行为验证码 */ private fun refreshVerifyCode(password: String, inviteCode: String?) { getAService<GrowthDataService>()?.checkVerifyCaptcha( GrowthDataService.VERIFYCODE_INVITE, { setPassword(password, inviteCode) }, { if (it is Response.Exception && (it.response.code == ServerCodes.VerificationCode.BEHAVIOR_VERIFICATION_CODE_ERROR)) { refreshVerifyCode(password, inviteCode) } else { _loadingState.value = LoadState.LoadError(it) } }) } class Factory @Inject constructor( private val setPasswordPresenter: SetPasswordPresenter, private val accountDataManager: AccountDataManager ) : ViewModelAssistedFactory<SetPasswordViewModel> { override fun create(handle: SavedStateHandle): SetPasswordViewModel = SetPasswordViewModel(setPasswordPresenter, accountDataManager) } }SetPasswordPresenter
class SetPasswordPresenter @Inject constructor( private val accountService: AccountService ) { /** * 新用户设置密码. * @param password String * @return Result<Any> */ suspend fun setPassword(password: String, inviteCode: String?) = safeApiCall { // 先校验密码 password.verifyNumberAndLetter().no { throw KException("密码必须包含数字和字母") } accountService.setNewPassword(SetPasswordRequest(password, inviteCode ?: "")) } }