Android中对MVC,MVP,MVVM架构的理解

博主前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住也分享一下给大家,
👉点击跳转到教程

以下是主流的对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框架,这是错误的理解。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

路宇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值