项目中 Dagger+ViewModel(LiveData) 使用步骤介绍

 

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

}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

黄毛火烧雪下

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值