ViewModel优雅的弹加载窗和获取Context

Posted 滔lt

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ViewModel优雅的弹加载窗和获取Context相关的知识,希望对你有一定的参考价值。

前言

目前安卓开发一般都是用的mvvm模式,Jetpack的ViewModel是必不可少的一部分,而vm的生命周期要比Activity和Fragment长的,所以其一般不推荐其直接持有A或F,因为可能会造成内存泄漏的问题,但是不传入,Context的获取和显示网络加载弹窗又成了问题.

正文

首先解决显示网络加载弹窗的问题,其有两种方案:

1.使用MutableLiveData

首先我们在BaseViewModel中加入弹窗的MutableLiveData

val dialogShow = MutableLiveData(false)

然后我们可以在A或F的onCreate中获取vm的时候注册dialogShow的变化监听

        val vm = ViewModelProvider(this).get(BaseViewModel::class.java)
        vm.dialogShow.observe(this) { isShow ->
            if (isShow) showWaitDialog() else dismissWaitDialog()
        }

但是这样写太麻烦了,可以使用Kotlin的代理来简单实现,这样不仅声明的更方便,且自动注册了观察者

    inline fun <reified VM : BaseViewModel> BaseActivity.baseViewModel() = lazy {
        val vm = ViewModelProvider(this).get(VM::class.java)
        vm.dialogShow.observe(this) { isShow ->
            if (isShow) showWaitDialog() else dismissWaitDialog()
        }
        vm
    }

    //Activity中
    val vm by baseViewModel<BaseViewModel>()

这样的优点很明显,vm完全不用持有A或F,但缺点是无法拿到A的Context

2.将BaseActivity或BaseFragment传入vm

就像androidViewModel一样,将A传入vm,但有的小伙伴可能会问了,那内存泄漏了怎么办?办法很简单,等下次重建回来的时候替换掉已经销毁的A即可,实现方式如下(示例为A,F也类似)

open class BaseViewModel(
    var baseActivity: BaseActivity//内部用于弹窗等的引用
) : ViewModel(){
    fun getContext() = baseActivity

    fun showWaitDialog(s: String?) = baseActivity.showWaitDialog(s)

    fun dismissWaitDialog() = baseActivity.dismissWaitDialog()
}

//快捷获取BaseViewModel
inline fun <reified VM : BaseViewModel> BaseActivity.baseViewModel(
    factory: ViewModelProvider.Factory? = null
) = lazy {
    val vm = ViewModelProvider(
        this,
        factory ?: BaseViewModelFactory(this@baseViewModel)
    ).get(VM::class.java)
    vm.baseActivity = this
    vm
}

class BaseViewModelFactory(private val baseActivity: BaseActivity) : ViewModelProvider.Factory {
    override fun <T : ViewModel?> create(modelClass: Class<T>): T {
        return modelClass.getConstructor(BaseActivity::class.java).newInstance(baseActivity)
    }
}

    //Activity中
    val vm by baseViewModel<BaseViewModel>()

这样在A的每个对象中第一次使用vm的时候就会把baseActivity替换为自身,也就不存在内存泄漏的问题了

这样就可以愉快的在vm中使用网络加载弹窗和获取Context了

以上是关于ViewModel优雅的弹加载窗和获取Context的主要内容,如果未能解决你的问题,请参考以下文章

移动站的优化技巧

React实现优雅的弹窗

React实现优雅的弹窗

创建 ViewModel 的新方式,CreationExtras 了解一下?

在 ViewModel 中获取 RegionManager

如何提高相册加载速度