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 ?: ""))
}
}