前言
在开发模式的演进过程中 MVC,MVP,MVVM一一登上舞台。但是并不意味着MVVM一定就比MVC MVP优秀。不同的项目有不同的体量,开发中要根据项目体量选择合适的开发模式。
市面上介绍mvvm的项目不在少数,但是看了很多,都在介绍源码原理,开发中的踩坑过程,而且有的是过时的资料,却很少见到能够直接从项目需求入手帮助不熟悉MVVM的开发者从入门到熟悉原理,再到框架优化的。这个空缺我来补充,如果提及到一些其他原理性的东西不便长篇展示,我会引用链接,或者引用他文的原文加以说明。
特别说明: 以下所有信息都基于截止到 2020年6月2日10点23分的 最新官方资料和源码版本。如果存在任何历史版本的差异,本文不会过分纠结。正文大纲
- 有关MVVM的几个重要组件
- ViewModel
- DataBinding
- LiveData
- LiveDataBus
- 案例实操
- MVVM的优缺点
正文
有关MVVM的几个重要组件
ViewModel
ViewModel 是androidx包中抽象类。它是谷歌开放给全世界开发者用来改善项目架构的一个组件。
既然是探索ViewModel的本源,那就从它的官方注解开始吧。
这段话的大意是:ViewModel是一个准备和管理Activity和Fragment的数据的类。它也可以掌控Activity、Fragment和应用中其他部分的通讯。 一个ViewModel总是关联到一个域(Activity或Fragment)被创建。并且只要域是存活的,ViewModel就会一直被保留。比如。如果域是一个Activity,ViewModel就会存活,直到Activity被finish。 换句话说,这意味着,如果它的持有者由于配置改变而被销毁时(比如屏幕旋转),ViewModel并不会被销毁。新的持有者实例,将会仅仅重新连接到已经存在的ViewModel。 ViewMode存在的目的,就是为Activity/Fragment 获得以及保留 必要信息。Activity / Fragment 应该可以观察到VIewModel的变化,ViewModel通常通过 LiveData或者DataBinding 暴露信息。你也可以你自己喜欢的使用 可观察的结构框架。 ViewModel仅有的职责,就是为UI管理数据,它不应该访问到你任何的View层级 或者 持有Activity 、Fragment的引用。谷歌爸爸其实已经把意思讲的很明白,上面一段话中有几个重点:
ViewModel 唯一的职责 就是 在内存中保留数据
多个Activity或者Fragment可以共用一个ViewModel
在屏幕旋转时,ViewModel 不会被重建,而只会连接到重新创建的Fragment/Activity
使用ViewModel有两种方式,LiveData或者
DataBinding(或者你可以自定义观察者模式框架),用他们来暴露ViewModel给V层
核心功能
ViewModel的核心功能:在适当的时机执行回收动作,也就是 onCleared() 函数释放资源。而这个合适的时机,可以理解为 Activity销毁,或者 Fragment解绑。借用一张图来解释,就是:
在整个Activity还处于存活状态时,ViewModel都会存在。而当Activity被finish的时候,ViewModel的onCleared函数将会被执行,我们可以自己定义函数内容,清理我们自己的资源,在Activity被销毁之后。该ViewModel也不再被任何对象持有,下次GC时它将被GC回收。基本用法
创建一个新的项目,定义我们自己的UserModel类,继承ViewModel:
import android.util.Log
import androidx.lifecycle.ViewModel
class UserModel : ViewModel() {
init {
Log.d("hankTag", "执行ViewModel必要的初始化")
}
override fun onCleared() {
super.onCleared()
Log.d("hankTag", "执行ViewModel 清理资源")
}
fun doAction() {
Log.d("hankTag", "执行ViewModel doAction")
}
}
在View层使用定义好的ViewModel:
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.lifecycle.ViewModelProvider
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// 获取ViewModel对象
val userModel = ViewModelProvider(this).get(UserModel::class.java)