美文网首页Android学习架构师Android 开发者必会
一文带你全面了解MVC、MVP、MVVM模式(含实例讲解)

一文带你全面了解MVC、MVP、MVVM模式(含实例讲解)

作者: Carson带你学安卓 | 来源:发表于2019-08-15 08:32 被阅读863次

    前言

    • Android开发中,当你梳理完需求后,你要做的并不是马上写下你的第一行代码,而是需先设计好整个项目的技术框架
    • 今天,我将全面介绍Android开发中主流的技术框架MVCMVPMVVM模式,并实例讲解MVP模式,希望您们会喜欢。

    目录

    示意图

    1. 为什么要进行技术框架的设计

    • 模块化功能
      使得程序模块化,即:内部的高聚合模块之间的低耦合
    • 提高开发效率
      开发人员只需专注于某一点(视图显示、业务逻辑 / 数据处理)
    • 提高测试效率
      方便后续的测试 & 定位问题

    切记:不要为了设计而设计,否则反而会提高开发量

    示意图

    2. Android开发主流的技术框架

    • 主要有MVCMVPMVVM 3种模式
    • 下面,我将详细 & 具体的介绍上述3种模式

    2.1 MVC模式

    • 角色说明
    示意图
    • 模式说明
    示意图
    • 该模式存在的问题:Activity责任不明、十分臃肿
      Activity由于其生命周期的功能,除了担任View层的部分职责(加载应用的布局、接受用户操作),还要承担Controller层的职责(业务逻辑的处理)
      随着界面的增多 & 逻辑复杂度提高,Activity类的代码量不断增加,越加臃肿

    2.2 MVP模式

    • 出现的原因
      为了解决上述MVC模式存在的问题,把分离Activity中的View层 和 Controller层的职责,从而对Activity代码量进行优化、瘦身,所以出现了MVP模式

    • 角色说明

    示意图
    • 模式说明
    示意图
    • 优点:(对比MVC模式)
    1. 耦合度更低:通过Presenter实现数据和视图之间的交互,完全隔离了View层与Mode层,二者互不干涉

    避免了ViewModel的直接联系,又通过Presenter实现两者之间的沟通

    1. Activity代码变得更加简洁:简化了Activity的职责,仅负责UI相关操作,其余复杂的逻辑代码提取到了Presenter层中进行处理

    2.3 MVVM

    为了更加分离M、V层,更加释放Activity的压力,于是出现了MVVM模式

    • 定义
      VM层:ViewModel,即 View的数据模型和Presenter的合体

    基本上与 MVP 模式完全一致,将逻辑处理层 Presenter 改名为 ViewModel

    • 模式说明
    示意图
    • 优点
      使得视图层(View)& 控制层(Controller)之间的耦合程度进一步降低,关注点分离更为彻底,同时减轻了Activity的压力

    本文主要讲解MVC和MVP模式,不过多阐述MVVM模式.


    3. MVC、MVP模式的区别

    示意图

    4. 三种模式出现的初衷

    • MVC模式的出现
      为解决程序模块化问题,于是MVC模式出现了:将业务逻辑、数据处理与界面显示进行分离来组织代码,即分成M、V、C层;
    • MVP模式的出现
      但M、V层还是有相互交叉、隔离度不够,同时写到Activity上使得Activity代码臃肿,于是出现了MVP: 隔离了MVC中的 M 与 V 的直接联系,将M、V层更加隔离开来,并释放了Activity的压力;
    • MVVM模式的出现
      为了更加分离M、V层,更加释放Activity的压力,于是出现了MVVM: 使得V和M层之间的耦合程度进一步降低,分离更为彻底,同时更加减轻了Activity的压力。

    下面,我将详细讲解一下最常用的MVP模式的核心思想 & 使用


    5. MVP模式详解

    此处主要详细分析MVP模式的核心思想,并实例说明。

    5.1 核心思想

    把Activity里的逻辑都抽离到ViewPresenter接口中去 & 由具体的实现类来完成。具体实现思路如下:

    1. Activity中的UI逻辑抽象成View接口 & 由具体的实现类来完成
    2. 把业务逻辑抽象成Presenter接口 & 由具体的实现类来完成
    3. Model类还是原来MVC模式的Model

    5.2 实现步骤

    MVP模式的UML

    示意图

    通过UML图可看出,使用MVP模式的步骤如下:

    示意图

    5.3 实例讲解

    本节通过一个 英语词典app实例 讲解 MVP模式具体的实现

    前言:工程项目的列表架构

    MVP技术架构的项目结构非常清晰:把MVP层分别分为三个文件夹:ModelViewPresenter,每个文件下分别是对应的接口和实现的类

    其中Model层的fanyi类是作为实现用GSON解析JSON信息的一个JavaBean

    步骤1:设置View层(IView接口 & 实现类)

    /**
      * View接口:IfanyiView
      * 需定义在实现类中需要用到的方法
      */
    
      public interface IfanyiView {    
    
        void init();//初始化   
        void SetInfo(String str); //输出翻译信息    
        void SetError(); //输出出错信息
    
        }
    
    /**
      * View实现类:MainActivity类
      * 注:由于MainActivity是对应View层的实现类,所以要实现View层的接口
      */
    
      public class MainActivity extends AppCompatActivity implements IfanyiView {   
    
          private EditText et;    
          private TextView tv;    
          CidianPresenter cidianPresenter;  // 声明了Presenter对应类 
    
            @Override    
            protected void onCreate(Bundle savedInstanceState) { 
                   super.onCreate(savedInstanceState); 
                   setContentView(R.layout.activity_main);        
                      // 实例化P对应类的对象和findView        
                       init();        
                    // 接受用户的输入  
                    findViewById(R.id.btnfanyi).setOnClickListener(new View.OnClickListener() {      
                  
                        @Override            
                        public void onClick(View v) {                
                        //将View层获得的数据传入Presenter层 ,注意还要传递MainActivity
                              cidianPresenter.InputToModel(et.getText().toString(), MainActivity.this);            
                             }        
                          });    
                        }    
    
                        @Override    
                        public void init(){        
                        //实例化P类的对象和findView        
                          cidianPresenter = new CidianPresenter(this);        
                          et = (EditText) findViewById(R.id.editText);        
                          tv = (TextView) findViewById(R.id.tv);    
                        }
    
                        @Override  
                        //输出出错信息   
                        public void SetError() {        
                          tv.setText("查询不成功,请检查网络");    
                         }
    
                        //输出翻译信息
                        @Override    
                        public void SetInfo(String str){        
                        tv.setText(str);    
                         }
                        }
    
      // 从上述代码可看出,MainActivity只做了FindView、setListener的工作(包含了cidianPresenter),简洁清爽!
    

    步骤2:设置Presenter层(创建IPresenter接口&实现类)

    /**
      * Presenter接口:ICidianPresenter
      * 需定义在实现类中需要用到的方法
      */
    
      public interface ICidianPresenter {    
          
         void InputToModel(String input,Context context); // 将View层获得的数据传入Model层
    
      }
    
    
    /**
      * Presenter层的实现类:CidianPresenter类
      * 注:由于CidianPresenter是对应Presenter层的实现类,所以要实现Presenter层的接口
      */
    
      public class CidianPresenter implements onfanyiListener,ICidianPresenter {    
          // 1. 声明View层对应接口、Model层对应的类    
          IfanyiView fyV;    
          fanyimodel fanyimodel;    
    
          // 2. 重构函数,初始化View接口实例、Model实例    
          public  CidianPresenter(IfanyiView fyV){        
              this.fyV = fyV;        
              fanyimodel = new fanyimodel();   
           }  
    
          // 3.将View层获得的数据传入Model层,注意要传递this.当前类
              @Override    
              public void InputToModel(String input, Context context){  
    
              fanyimodel.HandleData(input, context, this);    
    
              }    
              // 回调函数,调用UI更新  
              @Override    
              public void onSuccess(String str) {        
                  fyV.SetInfo(str);    }  
              // 回调函数,调用UI输出出错信息
              @Override    
              public void onError() {        
                  fyV.SetError();    } 
              }
     
          // 注:
          // a. 保留IfanyiView的引用,就可直接在CidianPresenter当前类进行UI操作而不用在Activity操作
          // b. 保留了Model层的引用就可以将View层的数据传递到Model层
    

    步骤3:Model层(Model层接口 & 实现类)

    /**
      * Model层接口:Ifanyi
      * 需定义在实现类中需要用到的方法
      */
      public interface Ifanyi {  
    
        void HandleData(String input,Context context,final onfanyiListener listener);    
        String fanyiToString(fanyi fy);
    
      }
    
    /**
      * Model层的实现类:fanyiModel类
      * 注:由于fanyiModel是对应Model层的实现类,所以要实现Model层的接口
      */
    
      public class fanyimodel implements Ifanyi {
    
          private fanyi fy = new fanyi();
    
          public void HandleData(String input,Context context,final onfanyiListener listener){
    
              // 使用Volley框架来实现异步从网络的有道API获取翻译数据
              RequestQueue mQueue = Volley.newRequestQueue(context);
              StringRequest stringRequest = new StringRequest("http://fanyi.youdao.com/openapi.do?keyfrom=Yanzhikai&key=2032414398&type=data&doctype=json&version=1.1&q="+input, new Response.Listener<String>() {
                  @Override
                  public void onResponse(String s) {
    
                      // 用Gson方式解析获得的json字符串
                      Gson gson = new Gson();
                      fy = gson.fromJson(s.trim(),fy.getClass());
    
                      // 回调监听器的函数把处理数据后的结果(翻译结果)返回给Presenter层
                      listener.onSuccess(fanyiToString(fy));
                  }
              }, new Response.ErrorListener() {
                  @Override
                  public void onErrorResponse(VolleyError volleyError) {
                      listener.onError();
                  }
              });
              mQueue.add(stringRequest);
          }
    
          public String fanyiToString(fanyi fy){
              // 处理解析后的json数据,转成UI输出的字符串
              String strexplain = "解释:";
              String strphonetic = "发音:";
              String strweb = "网络释义:";
              if (fy.basic == null){return "你所查找的还没有准确翻译";}
              for (int i = 0; i<fy.basic.explains.length; i++){
                  strexplain +=fy.basic.explains[i]+"\n";
                  if (i != fy.basic.explains.length-1 )
                  {strexplain +="\t\t\t\t";}
              }
              strphonetic += fy.basic.phonetic +"\n";
              for (int i = 0; i<fy.web.size(); i++){
                  for(int j = 0; j<fy.web.get(i).value.length;j++)
                  {
                      strweb += fy.web.get(i).value[j]+",";
                  }
                  strweb += fy.web.get(i).key+"\n";
                  strweb += "\t\t\t\t\t\t\t";
              }
              return strexplain+"\n"+strphonetic+"\n"+strweb;
          }
      }
    
    

    至此,关于MVP模式的实例讲解,讲解完毕。


    6. 总结

    • 本文主要讲解了Android开发中主流的技术框架MVCMVPMVVM模式
    • 下面我将继续对 Android中的知识进行深入讲解 ,有兴趣可以继续关注Carson_Ho的安卓开发笔记

    请点赞!因为你的鼓励是我写作的最大动力!

    相关文章阅读
    Android开发:最全面、最易懂的Android屏幕适配解决方案
    Android事件分发机制详解:史上最全面、最易懂
    Android开发:史上最全的Android消息推送解决方案
    Android开发:最全面、最易懂的Webview详解
    Android开发:JSON简介及最全面解析方法!
    Android四大组件:Service服务史上最全面解析
    Android四大组件:BroadcastReceiver史上最全面解析


    欢迎关注Carson_Ho的简书!

    不定期分享关于安卓开发的干货,追求短、平、快,但却不缺深度

    相关文章

      网友评论

        本文标题:一文带你全面了解MVC、MVP、MVVM模式(含实例讲解)

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