Android Jetpack 架构组件之 ViewModel

本文介绍了Android中ViewModel的作用,它能帮助将Activity的业务逻辑与UI数据分离,减少代码耦合。ViewModel在设备旋转等配置变更时保持存活,避免数据丢失。文中展示了如何创建和使用ViewModel,以及在Activity和Fragment中获取ViewModel实例的正确方式,强调了在实际开发中应遵循MVVM架构的分层原则。
摘要由CSDN通过智能技术生成

一、ViewModel 介绍

传统开发模式下,Activity、fragment 等任务繁琐,同时负责逻辑和UI,往往在一个比较大型的项目,一个 Activity 几千行代码算少的,让人看了就没下手的欲望,这也为啥衍生了 MVP、MVVM 的原因;而使用 ViewModel 的一个很重要的作用,就是可以为 Activity 分担一部分工作:专门存放界面相关的数据。也就是说,只要是界面上能看到的东西,它的变量都应该放在 ViewModel 中,而不是 Activity,这样就可以一定程序上减少 Activity 的逻辑。

另外,ViewModel 还有一个特性,就是当手机旋转等非正常退出时,它自身不会重建,即数据不会丢失,比如 Activity 在屏幕旋转时,会重建,从而导致数据丢失,虽然可以使用 onSaveInstanceState() 从onCreate()方法获取,但通过 ViewModel 就不用担心这个。

二、基本用法

首先添加ViewModel的依赖:

//ViewModel的依赖
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'

实际开发中,最好的规范是给 每一个 Activity / Fragment 创建一个对应的ViewModelAct/ViewModelFrag,然后继承ViewModel:

class ViewModelAct : ViewModel() {
    fun requestData(callBack: HttpClient.HttpCallBack<HomeArticleList>) {
        HttpClient.requestData(
            HttpClient.getService(ApiClient.HomePageAPI::class.java).homeArticleList(0.toString()),
            object : HttpClient.HttpCallBack<HomeArticleList> {
                override fun success(v: HomeArticleList) {
                    if (v.errorCode != 0) {
                        failed(Throwable())
                        return
                    }
                    //TODO:UPDATE UI
                    Logging.log("数据请求成功啦:$v${v.data.datas[0]}")
                    callBack.success(v)
                }

                override fun failed(t: Throwable) {
                    Logging.log("请求失败:${t.toString()}")
                }
            })
    }
}

接着,我们在Activity里面通过ViewModelProvider 获得 ViewModel 的实例,由于 ViewModel 有自己的生命周期,并且生命周期长于activity,如果直接在onCreate 创建实例,这样每次都会创建一个新的实例,这样就无法保存数据了。所以,ViewModel 的实例创建应该这样:

var viewModel: ViewModelAct = ViewModelProvider(this).get(ViewModelAct::class.java)

小提示:
ViewModel初始化(在Activity和Fragment里面的初始化是一样的):

ViewModel xxxmViewModel = ViewModelProvider(this).get(xxxViewModel::class.java)
新版本改成以下方式:
MainViewModel mMainViewModel = new ViewModelProvider(this).get(MainViewModel.class);

Fragment里面还可以使用:

ViewModel xxxmViewModel = ViewModelProvider(getActivity()).get(xxxViewModel::class.java)
新版本改成以下方式:
MainViewModel mMainViewModel = new ViewModelProvider(getActivity()).get(MainViewModel.class);

这里需要说明的是:Fragment里面使用的ViewModelProvider(getActivity()).getxxx,也可以使用ViewModelProvider(this),如果使用getActivity()则在Activity中的Fragment与Activity使用相同的ViewModel。

最后Activity里面的代码如下:

class ViewModelActivity : BaseActivity() {
    lateinit var viewModel: ViewModelAct
    lateinit var binding: ActivityViewModelBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = DataBindingUtil.setContentView(this, R.layout.activity_view_model)
        viewModel = ViewModelProvider(this).get(ViewModelAct::class.java)
        btnViewModel.setOnClickListener {
            viewModel.requestData(object : HttpClient.HttpCallBack<HomeArticleList> {
                override fun success(v: HomeArticleList) {
                    //TODO:UPDATE UI
                    binding.wanandroid = v
                }

                override fun failed(t: Throwable) {
                    //TODO:抛出异常
                }
            })
        }
    }
}

需要注意的是,上面的例子中,requestData()的网络请求不应该是放在ViewModel里面,应该是在Model里面,这里因为是在demo里面,学习心得技术,就没有太严谨的要求自己。所以在实战开发中,我们还是应该严格按照MVVM的分层结构来实现。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值