先上图
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太香了。相见恨晚,往事回想,泪目( Ĭ ^ Ĭ )
Copyright© 2013-2019