博主前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住也分享一下给大家,
👉点击跳转到教程
以下是主流的对MVC,MVP,MVVM架构理解的图示
一、对于MVC架构的理解:
1、首先编写Model:
class DataCenter {
companion object {
fun getData() = listOf("Hi", "Android")
}
}
2、在MVC中,activity_m_v_c.xml对应的是视图部分,就是View层
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MVCActivity">
<EditText
android:id="@+id/data1View"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<EditText
android:id="@+id/data2View"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<Button
android:id="@+id/save"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="save" />
</LinearLayout>
3、Controller控制器对应的就是Activity
class MVCActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_m_v_c)
val data = DataCenter.getData()
data1View.setText(data[0])
data2View.setText(data[1])
}
}
但是随着软件越来越来复杂,会发现这样的写法不是太好,有些缺陷,Controller和View越来越耦合了,Controller指挥View去显示,具体怎么显示Controller是不关注的,比如setContentView(R.layout.activity_m_v_c),和具体的摆放逻辑全部是在xml中进行摆放布局的,但是Controller层要操控具体的数据应该放在哪个控件上,随着软件越来越大,Controller和View层的关系越来越紧密,所以引入了MVP架构。
二、对于MVP架构的理解:
1、Model层对应的代码
class DataCenter {
companion object {
fun getData() = listOf("Hi", "Android")
}
}
2、Presenter对应的代码如下
class Presenter(private val iView: IView) {
fun init() {
val data = DataCenter.getData()
iView.showData(data)
}
interface IView {
fun showData(data: List<String>)
}
}
3、View层对应的为MVPActivity和该Activity对应的xml
class MVPActivity : AppCompatActivity(), Presenter.IView {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_m_v_c)
Presenter(this).init()
}
override fun showData(data: List<String>) {
data1View.setText(data[0])
data2View.setText(data[1])
}
}
在MVP架构中,Presenter通过Model拿到数据,通过View进行显示,具体怎么拿数据和怎么显示Presenter不关心,Model层完全掌握数据的读和写,View层Activity和xml完成掌握了如何显示。MVP把View部分和Presenter部分完全拆开,达到更加松散的一种效果,不再那么耦合。
三、对于MVVM架构的理解:
Android中的MVVM其实就是MVP加上数据绑定,程序中的数据可以分为三类:外部数据(数据库数据,文件数据和网络数据),内存数据(Java中的一些变量),表现数据(界面展示的数据)。
数据双向绑定:表现数据和内存数据,自动实现双向更新。比如一个EditText输入框,输入不同的文本,表现数据变化了,内存数据也自动更新,或者内存数据变化了,输入框中的文本也发生了变化这就是双向绑定。
还有就是界面数据改变了,会改变内存数据,内存数据改变了会改变数据库中的数据,反过来,数据库中的数据改变了,内存数据会发生改变,内存数据改变了会导致表现数据发生改变,界面发生变化。这种三层的数据改变也是属于MVVM,但是通常MVVM中的数据绑定是内存数据,和表现数据之间的联动。
MVP架构加上DataBinding就是MVVM,MVC和MVP架构性质更强,提供的是一种规范和一种规则,而MVVM是一种框架而不是架构,框架更像是一个库,用这个库就可以用来开发了,不用遵守规则,你用这个库就自动遵守了规则。而MVVM更像一种框架,双向绑定是一种工具,一个库,因为自己实现起来比较复杂,需要用其框架和库比如Android中谷歌推出的DataBinding。
下面实现一个简单的MVVM框架,并自己实现双向绑定。
1.Model层对应的代码如下
class DataCenter {
companion object {
fun getData() = listOf("Hi", "Android")
}
}
2.View层为MvvmActivity和对应的xml
class MvvmActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_m_v_c)
ViewModel(data1View, data2View).init()
val data = DataCenter.getData()
data1View.setText(data[0])
data2View.setText(data[1])
}
}
3.ViewModel对应的VM,来实现内存数据与表现数据的双向绑定
ViewModel类如下:
class ViewModel(data1View: EditText, data2View: EditText) {
private var data1: StringAttr = StringAttr()
private var data2: StringAttr = StringAttr()
init {
ViewBinder.bind(data1View, data1)
ViewBinder.bind(data2View, data2)
}
fun init() {
val data = DataCenter.getData()
data1.value = data[0]
data2.value = data[1]
}
}
ViewBinder类实现双向绑定
class ViewBinder {
companion object {
fun bind(editText: EditText, stringAttr: StringAttr) {
editText.doAfterTextChanged {
if (!TextUtils.equals(stringAttr.value, it)) {
stringAttr.value = it.toString()
println("表现数据通知内存!${it}")
}
}
stringAttr.onChangeListener = object : StringAttr.OnChangeListener {
override fun onChange(newValue: String?) {
if (!TextUtils.equals(stringAttr.value, newValue)) {
editText.setText(newValue)
println("内存通知表现数据!${newValue}")
}
}
}
}
}
}
StringAttr类监听数据发生变化
class StringAttr {
var value: String? = null
set(value) {
field = value
onChangeListener?.onChange(value)
}
var onChangeListener: OnChangeListener? = null
interface OnChangeListener {
fun onChange(newValue: String?)
}
}
这样一个简单的MVVM框架就实现了,Android中Google推出的ViewModel,主要目的是在设备配置发生变化(例如旋转屏幕)或者活动(Activity)被系统杀死后重新创建时,保存和管理UI相关的数据,以便恢复UI的状态。并不是用了这个ViewModel就是MVVM框架,这是错误的理解。