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了

对Kotlin或KMP感兴趣的同学可以进Q群 101786950

如果这篇文章对您有帮助的话

可以扫码请我喝瓶饮料或咖啡(如果对什么比较感兴趣可以在备注里写出来)

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值