美文网首页Android开发
Android架构篇:mvc、mvp、mvvm浅谈

Android架构篇:mvc、mvp、mvvm浅谈

作者: 10块钱new一个对象 | 来源:发表于2020-11-26 20:37 被阅读0次

    MVC

    在我们的开发中,通常是这样去描述MVC的

    • view:xml、动态添加的view绑定等
    • model:获取数据的模型层
    • Controller:Activity,Fragment等
    1. Activity通过setContentLayout和findviewByid将视图与控制器绑定
    2. setOnclick等监听绑定了各类视图交互
    3. 当点击事件触发的时候,假设网络请求,那么点击按钮的时候,我们要model发送一个网络请求
    4. 所以Activity同时也要持有Model对象,当model请求返回了数据之后,通知view去更新,那么代码可以这样写
    V
    xml
    <TextView...>
    
    C
    Activity{
        onCreate{
            //Model
            String data = Model.getData();
            //View
            tv.setText(data);
        }
    }
    
    M
    Model{
        //直接返回用的比较少,一般都是接口回调,这里简化了
        static String getData(){
            retrun "MVC"
        }
    }
    

    MVC的流程

    其实我认为MVC不应该把M、V、C拆开去看,其实可以看作就是就是++M++、++VC++两个部分更好理解一些

    • Controller和View->Activity控制了View:首先Activity持有了view,我们知道controller通常是负责流程控制的,在我们日常的开发中,其实Activity就可以大概理解为Controller,所以可以理解这里的Controller就controll(控制)了View,View的更新都是需要通过Controller去控制的,这是第一点
    • Controller和Model->Controller也控制了Model:View本身并不会主动去向model获取数据,Controller可以询问Model来获取数据,然后决定是否更新View
    • View和Model->数据和视图需要保持一致:view的操作可以触发model的改变,比如提交数据,model的更新也需要view改变,比如接口数据变化
    • 一个完整的MVC业务应该是这样的,以注册功能为例
      • View层用户输入了用户名密码,点击提交,将事务交给Controller
      • Controller监听了View层的提交按钮事件,然后提交数据给Model
      • Model拿到了Controller发送的事件,然后请求接口,从服务器拿到了数据,回调给了Controller
      • Controller拿到了数据{data:"sucess",message:"注册成功"},这个时候该通知View了
      • View把Controller的数据进行展示,接下来的流程控制继续交给Controller
      • 倒计时三秒之后Controller通过startActivity直接进首页了
      • 所以,其实这里一个完整的MVC流程是V-C-M-C-V-C,M和V从不相邻,说明他们直接并不直接交互
    • 在这里,我们可以看到其实model和view是隔离开的,并没有直接交互,这是我们日常开发中常用的方式,网上又很多文章讲model.setView(..。),然后在model内view实现更新,这其实很不符合安卓开发的常理,而且我们也完全没有必要为了写经典MVC模式代码而做一些让我们开发更加复杂化的工作

    MVC的问题

    其实MVC主要的问题就是C太过繁重,要负责的东西太多,既要负责询问Model,又要负责View的更新,不累么,累啊,太累了,而且代码多了看起来都头痛,这是即便你代码写的再工整都会觉得烦,对于后期维护来讲很不友好,而且代码是真的容易越写越乱,Activity中的代码太多了,所以MVP的出现其实是大大了解放了Activity

    最后请记住把所有业务逻辑和界面更新操作都写进 Activity 的写法不叫 MVC。

    MVP

    MVP在MVC基础上,对Controller进行了拆分

    • 将Activity完全抽象为一个View
    • 增加Presenter绑定了视图View和模型Model
    • 当需要进行数据的获取时,View通过Presenter进行获取,View并不关心Presenter内部是怎么实现的
    • 当数据更新时,Presenter通过接口回调的方式通知了View去更新
    • 所以代码可以这样去写

    Presenter

    P
    class Presenter{
        Model model;
        View view;
        // P 持有了View 和 Model
        Presenter(View v){
            model = new Model();
            view = v;
        }
    
        doPost(){
            String data = model.getData();
            view.showData(data);
        }
    
    }
    

    Model

    M
    Model{
        String getData(){
            retrun "MVP"
        }
    }
    

    View

    V
    xml
    <TextView...>
    
    Activity implements View{
        onCreate{
            //P
            Presenter p = new Presenter(this);
        }
    
        @override
        showData(String data){
            tv.setText(data);
        }
    }
    
    interface View{
        void showData(Obect data);
    }
    

    MVP的流程

    还是以上面的注册流程为例

    • 首先View点击事件被触发,View通知Presenter去提交注册
    • Presenter通知Model,我要注册了
    • Model拿到了注册信息,返回注册成功信息
    • 这时候还是在Presenter内,Presenter通过接口回调给View
    • View接收到了回调,更新视图、跳转
    • 所以整个流程是V-P-M-P-V, 同样M和V不相邻,不直接交互

    MVP与MVC的比较

    通过上面的梳理,我们似乎发现MVP跟MVC特别像啊,甚至MVC中的代码反倒是精简很多,没错,是的,所以这也就是MVC和MVP根本没必要争论谁好谁坏的原因,那个适合,那个就是最好的

    • 其实MVP跟MVC相比,代码量并没有减少(当然这里的Presenter可复用可以一定程度减少代码,但这里不抬杠),反倒是增加了接口和类
    • MVP在我看来其实就是进化版的MVC,依赖接口编程,类的职责更加单一,职责明确这都是他的优点
    • 其实MVP主要的变化就是在MVC上增加了一个P,MVC中的M不变,V作为MVP中V的一部分,C拆分为了View和Presenter,
      • Model:获取数据的模型层
      • View:Activity、xml、动态添加的view绑定等
      • Presenter:连接view和Model

    MVP的特点

    • 接口太多,类爆炸(写一个页面通常要建很多的类);
    • 寻找数据源困难,因为MVP都是使用接口,所以查找数据的时候都是接口(其实我就很疲倦于不停在各个接口间奔波),不像MVC那样一条路跑到黑那样“爽”;
    • 对于功能十分简单的应用来讲,MVC更快捷,MVP就算了
    • 开发的时间成本高(让我想起react比vue更能增加就业机会那个梗)
    • 由于层次分明,并且依赖接口,所以代码可读性确实是更好的
    • 可维护性也是明显要好于MVC的

    MVVM

    在前端开发中MVVM使用的特别普遍,其特性就是

    • model更新了,view也更新
    • view上的某些输入改变了,model也改变了

    类似react,vue等前端框架都帮我们实现了Model-View,View-Model的双向绑定,即这个过程是自动的,开发者按照开发规范去编写代码就可以了
    但是在安卓开发中我们要手动去实现这个(虽然ViewModel+LiveData极大地帮我们简化了双向绑定的过程)

    我理解的MVVM,其实就是一个加了数据的MVP/MVC

    什么是数据绑定:

    • 外部数据(数据库数据、网络数据)、内存数据(Java 代码中的变量)、表现 数据(界面中展示的数据)中的外部表现数据和内存数据互相自动更新。
    • 另外,MVVM 有时候还可以给你的内存数据和数据库数据做关联监听,让你的 这三种数据实现进一步的联动。

    MVVM的实现

    MVVM可以分成三个部分去解读,MODEL,VIEW,VIEW-MODEL

    • MODEL提供数据

      object DataCenter{
        fun getData():String{
          return StringAttr().value!!;
        }
      }
      
    • View负责数据的展示

      class MvvmActivity:AppCompatActivity() {
        override fun onCreate(savedInstanceState: Bundle?) {
          super.onCreate(savedInstanceState)
          setContentView(R.layout.layout_mvvm)
      
          var mvvmText: EditText = findViewById(R.id.mvvmText);
      
          ViewModel(mvvmText).init();
        }
      
      }
      
    • ViewModel负责view和model的双向绑定

      • view我们可以设置监听,然后model.setValue()的方式就可以更新model了
      • model的数据发生改变,view上的渲染通过view.setText()的方式也发生变化
      class ViewModel (textView: EditText){
      
        var data:StringAttr = StringAttr()
      
        init {
          ViewBinder.bind(textView,data);
        }
      
        fun init(){
          val data = DataCenter.getData();
        }
      
      }
      

      在这里我们使用ViewBinder去双向绑定

      class ViewBinder {
        companion object{
          private const val TAG = "ViewBinder"
          //双向绑定
          fun bind(editText: EditText,stringAttr: StringAttr){
            editText.addTextChangedListener(object : TextWatcher {
              override fun afterTextChanged(s: Editable?) {
                if (!TextUtils.equals(stringAttr.value,s)){
                  stringAttr.value = s.toString();
                  Log.d(TAG,"view通知model改变数据了:${s}")
                }
              }
              ...
            })
            stringAttr.onChangeListener = object : OnchangeListener {
              override fun onChange(newVal: String?) {
                if (!TextUtils.equals(newVal,editText.text)) {
                  editText.setText(newVal)
                  Log.d(TAG,"model通知view改变文字了:${newVal}")
                }
              }
            }
          }
        }
      }
      

    这样无论是视图和数据就实现了绑定,你变我也变,你不变我也不变

    MVVM流程

    依然以注册功能为例

    • 当用户输入时,View-Model工作了,负责将数据与UI同步更新
    • 输入完成后,下面点击注册提交按钮,View获取同步后的Model数据
    • Model把我们要提交的数据进行提交,服务器返回了注册成功的信息
    • 这些返回的数据通过ViewModel重新绑定到View上,View更新了
    • 倒计时三秒之后,View控制层跳转到了首页
    • 所以整个流程是VM-V-M-VM-V

    MVVM 和 MVC、MVP 在定位上的区别

    • MVC MVP 的架构性质更强:它提供设计规范
    • 而 MVVM 是一个框架,像一个库:它提供数据绑定的功能特性

    MVVM 和 Android Jetpack

    和 MVVM 相关的 Jetpack 组件是 DataBinding,而不是 ViewModel

    相关文章

      网友评论

        本文标题:Android架构篇:mvc、mvp、mvvm浅谈

        本文链接:https://www.haomeiwen.com/subject/ghbziktx.html