个人对MVVM模式理解和介绍
MVVM由以下三个部分组成
- Model
- JavaBean
- DataSource
- View
- Layout Xml
- View、ViewGroup、Activity、Fragment的View功能
- ViewModel
- DataBinding自动生成的对象
- AndroidViewModel的子类
- View、ViewGroup、Activity、Fragment的统筹管理功能
MVVM是Model+View+ViewModel的简写,是一种代码架构模式。
Model
Model层主要包含两个内容JavaBean和DataSource
JavaBean
JavaBean就是传统的数据类,实现简单的get set方法。在不需要set方法的时候,不要创建set方法。Kotlin可以忽视
DataSource
DataSource是数据的来源,这个类用单例的方式来获取。因为使用单例模式能很好的在Application运行的过程中获取需要的数据,下面是例子。
class XXXDataSource private constructor(val context: Application) {
companion object {
private var INSTANCE: XXXDataSource? = null
@JvmStatic
fun getInstance(context: Application): XXXDataSource {
return INSTANCE ?: XXXDataSource(context).apply { INSTANCE = this }
}
}
全局属性通常申明需要长期保存或者需要跨页面多次使用的针对Application的全局对象,比如用户数据。
方法的部分主要是和服务器进行数据获取,或者是和本地的数据缓存进行交互。比如RemoteGetData(远程获取数据),CacheGetData(内存缓存数据),DatabaseGetData(数据库获取数据)
class XXXDataSource private constructor(val context: Application) {
//用户数据
var userInfo: UserInfo? = null
var getUserInfoAsync(callback:callback){
if(userInfo!=null){
callback.back(userInfo)//内存缓存数据
}else {
val info:UserInfo?=getLocalData()//Database数据,或者shareference数据
if(info!=null){
callback.back(userInfo)
}else{
getUserInfoRemote(callback)//网络获取数据
}
}
}
}
View
包含Layout Xml和View、ViewGroup、Activity、Fragment的View功能
Layout Xml
通过DataBinding的处理Layout Xml其实变成了一种可以编辑的代码,不仅仅只是布局最开始的状态了,而是可以配合数据变化而进行变化的。具体用法参照网络上DataBinding的参考文档和各种使用的工程
View、ViewGroup、Activity、Fragment的View功能
这个是我个人的理解。 其实Activity和Fragment有生命周期,而且需要在这个进行View的更改,所以是又有View的功能,又有ViewModel的功能,耦合性是比较高的。简单来说就是在这些里面,只操作View的变化,不要管数据如何获取,有点像MVP中的V层的作用,但是不需要写基础接口,耦合性其实更低,而且更灵活。
ViewModel
ViewModel层包含DataBinding自动生成的对象、AndroidViewModel、View、ViewGroup、Activity、FragmentActivity的统筹管理功能
DataBinding自动生成的类
这些类是自动生成的,而生成和xml的编写有关系,或者是写了一些自定义的DataBinding的xml属性,使用就行了.
AndroidViewModel
AndroidViewModel是Google针对MVVM架构而专门推出的一个基类,ViewModel可以用在多个Activity,Fragment中。比如手机获取验证码这种功能,就可以重复多个页面里使用。
在AndroidViewModel中,需要用Observable对象(不是rx的Observable)和xml中的View绑定,来通知数据的更改。或者使用LiveEvent在Activity或者Fragment中注册,来进行一些Toast,Snackbar,Dialog的显示。
MVVM-N和MVVM-L
MVVM-N和MVVM-L是我针对MVVM的两种理解的扩展,并不是对MVVM模式的基础架构的变更,这个L表示的是Listener,N表示Navigator。
具体理解是,View层和ViewModel需要进行点击交互的时候,比如Activity点一个按钮,ViewModel进行数据请求,当ViewModel获取到数据后需要返还给Activity进行页面跳转。我们可以使用LiveEvent进行注册。但是有些使用LiveEvent满足不了这个需求。总会遇到这种问题。
L模式
L是在Layout Xml中声明的Listener接口,和ViewModel是同一层级的
<layout>
<data>
<variable
name="listener"
type="UserListener" />
<variable
name="viewModel"
type="UserViewModel" />
<data>
<Button
android:onClick="{(view)->listener.click(view)}"/>
</layout>
然后在Activity的代码中,去调用ViewModel的方法
class UserActivity:AppcompatActivity(),UserListener{
fun onCreate(bundle:Bundle){
val viewModel=...
}
fun click(view:View){
//show某个dialog,dialog点击确认后才能调用ViewModel的方法
viewModel.click(/*异步的话这里需要传一个回调*/)
}
}
N模式
N是让Activity实现Navigator接口,然后把这个Navigator对象传给ViewModel
class UserActivity:AppcompatActivity(),UserNavigator{
//UserNavigator有个方法是click
fun onCreate(bundle:Bundle){
val viewModel=...
viewModel.navigator=this
}
fun click(){
//show某个dialog,dialog点击确认后才能调用ViewModel的方法
viewModel.click(/*异步的话这里需要传一个回调*/)
}
}
<layout>
<data>
<variable
name="viewModel"
type="UserViewModel" />
<data>
<Button
android:onClick="{(view)->viewModel.click()}"/>
</layout>
class UserViewModel(app:Application):AndroidViewModel(app){
val navigator:UserNavigator?=null
fun click(){
navigator.click()
}
}
就我个人的理解而言,我更喜欢MVVM-L的方式。当然,也可以使用LiveEvent注册的方式来处理某些dialog的显示。具体的话,还是看使用场景