前言
什么是MVVM?先上图
1813550.png
viewmodel可以理解为桥梁,通过viewmodel 将 View和Model双向绑定,数据的变化可以直接作用在View上,就是MVVM,其实MVVM,MVP都是在MVC的基础上演变而来。
MVVM与DataBinding的关系
MVVM是架构思想,没有固定的套路,你可以基于这个思想整个自己的MVVM框架。而DataBinding就是基于MVVM思想实现的一个框架。目前也是android MVVM 开发的主流框架。
JetPack的ViewModel 与MVVM中ViewModel的关系
有位大佬说过它们两个没有关系不是一个东西。其实这句话说要看怎么说. JetPack 的 ViewModel 官方给的定义是 旨在存储和管理生命周期的方式与UI相关的数据 ,而MVVM中的viewmodel是连接View与Model的纽带。
不使用jetPack的ViewModel,我们可以自己实现一个ViewModel
class Presenter { val size = ObservableField<Int>() fun numChange() { size.set(size.get() + 1) size.notifyChange() } }
xml 数据绑定
<?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools"> <data> <variable name="presenter" type="com.example.myapplication.Presenter" /> </data> <LinearLayout android:gravity="center_horizontal" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <TextView android:layout_marginTop="50dp" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{presenter.size.toString()}" /> <Button android:onClick="@{()->presenter.numChange()}" android:layout_marginTop="20dp" android:background="@color/black" android:text="点击数字自增" android:layout_width="150dp" android:layout_height="wrap_content"> </Button> </LinearLayout> </layout>
如果是这样的情况,MVVM ViewMoel 是我们自己定义的Presenter类实现的,JetPack的ViewModel 和MVVM的ViewModel确实没有关系。但是因为我们自己定义的ViewModel实现类,在实际开发中会有很多问题,最突出就是没有生命周期的管理。
所以你会想到什么?
用JetPack的ViewModel来承担MVVM的ViewModel的职责。
class MainViewModel : ViewModel() { val size = MutableLiveData<Int>().apply { this.value = 0 } fun numChange() { size.postValue((size.value ?: 0) + 1) } }
<?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools"> <data> <variable name="mainViewModel" type="com.example.myapplication.MainViewModel" /> </data> <LinearLayout android:gravity="center_horizontal" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <TextView android:layout_marginTop="50dp" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{mainViewModel.size.toString()}" /> <Button android:onClick="@{()->mainViewModel.numChange()}" android:layout_marginTop="20dp" android:background="@color/black" android:text="点击数字自增" android:layout_width="150dp" android:layout_height="wrap_content"> </Button> </LinearLayout> </layout>
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val binding = DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main) binding.lifecycleOwner = this val viewModel = ViewModelProvider(this).get(MainViewModel::class.java) //将viewModel 数据 赋值给 View 声明的变量 binding.setVariable(BR.mainViewModel,viewModel) } }
gradle 的anroid 配置
dataBinding { enabled = true }
gradle 的 dependencies 配置
dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" implementation 'androidx.core:core-ktx:1.3.2' implementation 'androidx.appcompat:appcompat:1.2.0' implementation 'com.google.android.material:material:1.2.1' implementation 'androidx.constraintlayout:constraintlayout:2.0.4' testImplementation 'junit:junit:4.13.1' androidTestImplementation 'androidx.test.ext:junit:1.1.2' androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' def lifecycle_version = "2.2.0" implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version" implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version" implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version" }
如果是这中情况,那么JetPack的ViewModel 等同于 MVVM的ViewModel,当然JetPack的ViewModel还能干其他事,承担MVVM的ViewModel 仅是一个兼职。
android.gif
对比了一下Vue的MVVM的实现
<template> <div> <p>{{ size }}</p> <button @click="numChange">点击数字自增</button> </div> </template>
<script> export default { methods: { numChange: function () { this.size = this.size + 1 } }, data: function () { return { size: 0 } } } </script>
<style lang="less" scoped></style>
vue.gif
两者都是在View层绑定了 size 变量 , 数据声明与方法的都在ViewModel中,(Vue的export default 也承担了MVVM中viewmodel的职责,当然了这也是它的一个兼职)
补充
DataBinding 中的bindAdapter 还可以将每个控件单独处理,使结构更加松散,逻辑不会耦合在Activity中或者ViewModel里,特别在复杂的交互场景下需求迭代频繁的时候,MVVM太香了。相见恨晚,往事回想,泪目( Ĭ ^ Ĭ )
查看更多关于关于 Android MVVM 一些理解与实践的详细内容...