了解MVC、MVP、MVVM模式

news2025/3/16 1:44:13

前言

  • Android开发中,当你梳理完需求后,你要做的并不是马上写下你的第一行代码,而是需先设计好整个项目的技术框架
  • 今天,我将全面介绍Android开发中主流的技术框架MVCMVP 与 MVVM模式,并实例讲解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开发中主流的技术框架MVCMVP 与 MVVM模式

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/645722.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Android启动优化实践

作者&#xff1a;95分技术 启动优化是Android优化老生常谈的问题了。众所周知&#xff0c;android的启动是指用户从点击 icon 到看到首帧可交互的流程。 而启动流程 粗略的可以分为以下几个阶段 fork创建出一个新的进程创建初始化Application类、创建四大组件等 走Applicatio…

uni-app配置Vant Weapp

uni-app配置vant-------浏览器运行环境下不兼容 1.创建uni-app项目2.创建wxcomponents目录3. 安装vant需要的模块包3.1找一个空文件cmd 进入执行3.1.1通过 npm 安装3.1.2通过 npm 安装 3.2.1获取dist文件 4.将dist内容复制到wxcomponents目录下5.1 使用vant5.1使用button按钮5.…

Qt扫盲-QKeyEvent 键盘事件

QKeyEvent 键盘事件 一、概述二、事件传播三、常用属性1. key()2. modifiers()3. isAutoRepeat()4. text() 四、简单组合键代码 一、概述 QKeyEvent 是Qt 里面描述键盘事件的一个属性类&#xff0c;所有的事件本质上来说其实就是一个信息包&#xff0c;而这个包里面就是有这个…

探索Redis内部数据结构

Redis支持多种数据结构&#xff0c;每种数据结构都有其特定的用途。下面对Redis支持的主要数据结构进行详细阐述&#xff1a; 一、字符串&#xff08;String&#xff09; 字符串是Redis最基本的数据结构&#xff0c;可以存储一个字符串或者二进制数据&#xff0c;例如图片、序…

Echarts—词云库(echarts-wordcloud)配置详解和使用(可自定义形状)

词云库的详解 前言安装基本配置详解具体使用步骤&#xff08;Vue为例&#xff09;自定义展示形状 前言 我们经常会看到一些网站或者页面有一堆五颜六色的词汇的聚在一块&#xff0c;有大有小的散落着&#xff0c;看着挺好看的&#xff1b; 也许项目中也会涉及到显示一些关键词…

【Linux脚本篇】Linux循环语句-while

目录 &#x1f341;while的语法格式 &#x1f341;while循环案例 &#x1f343;案例一&#xff1a;输出10-1的降序 &#x1f343;案例二&#xff1a;输出10的升序和降序 &#x1f343;案例三&#xff1a;批量创建用户 &#x1f341;内置跳出循环 &#x1f343;案例一&#xff1…

火山引擎 DataLeap:一个易用、高效的数据目录,是如何搭建的?

更多技术交流、求职机会&#xff0c;欢迎关注字节跳动数据平台微信公众号&#xff0c;回复【1】进入官方交流群 企业如何找到数据、了解数据以及使用数据&#xff1f; 这离不开数据目录的能力。数据目录有着类似于“字典”的作用&#xff0c;能够帮助数据生产者和使用者快速定位…

ESXI 环境搭建和配置

ESXI 环境搭建和配置 ESXI简介 ESXi专为运行虚拟机、最大限度降低配置要求和简化部署而设计。只需几分钟时间&#xff0c;客户便可完成从安装到运行虚拟机的全过程&#xff0c;特别是在下载并安装预配置虚拟设备的时候。 在VMware Virtual Appliance Marketplace 上有800多款…

RabbitMQ 安装

目录 一、安装RabbitMQ1、Linux 安装⑴、官网rpm包安装①、下载rpm安装包官网下载erlangrabbitmq packagecloud下载erlangrabbitmq ②、安装 erlang③、安装rabbitmq ⑵、packagecloud快速安装⑶、添加用户账号及权限并登陆⑷、卸载erlang与rabbitmq卸载rabbitmq卸载erlang 2、…

积聚产业发展新动能|2023开放原子全球开源峰会OpenAtom OpenHarmony分论坛成功举办

6 月 12 日&#xff0c;以“OpenHarmony 共建开放&#xff0c;共享未来”为主题的 2023 开放原子全球开源峰会 OpenAtom OpenHarmony&#xff08;以下简称“OpenHarmony”&#xff09;分论坛在北京北人亦创国际会展中心第一报告厅圆满落幕。开放原子开源基金会理事长孙文龙、华…

【mongoDB数据库基本操作】

mongoDB 基本命令使用 mongoDB数据库基本操作1、连接/创建数据库3、查看数据库4、删除数据库 表的基本操作1、创建表2、删除表3、查询表4、更新表删除表中的记录 mongoDB数据库基本操作 连接mongoDb服务器 进入到mongoDb安装目录 cd /data/mongodb/bin 使用./mongo连接到本…

为什么你的领导,总是挑刺,要求你要有自己的思考?

为什么你的领导&#xff0c;总是挑刺&#xff0c;要求你要有自己的思考&#xff1f; 如何思考&#xff1f;其实有方法论和框架&#xff0c;照这做&#xff0c;也能提升自己的思考能力和维度。 尴尬的问题 在职场的给位是否遇到过这种情况。领导在开完一次沟通会&#xff0c;或…

公元前后的王莽与屋大维

公元元年前后&#xff0c;地球的两端同时产生了两个辉煌的大国&#xff0c;z国和罗马。 我国经历了漫长而又松散的分封制后&#xff0c;在秦帝国时期实现了大一统&#xff0c;在那个时代&#xff0c;因为分封制有效的管理半径最多也就是500公里左右&#xff0c;所以非常不适合…

牛客网1658 页的 Java 岗面试突击手册,GitHub已下载量已过百万

不得不说程序员除了做项目之外&#xff0c;提升自己技能最快的方式就是【看书&#xff01;】和【刷题&#xff01;】&#xff0c;这里说的刷题不是无脑刷&#xff0c;而是要明白面试官为什么会问这个问题&#xff0c;以及这个问题的意义在哪里&#xff01; 今天带来的是全新升…

Beyond Compare 4 正版激活码 -变化是不可避免的,因此,请使用最好的工具对其进行管理。

Beyond Compare 是开发人员、系统管理员和其他人用来比较、合并和同步数据的软件应用程序。它可以在Windows&#xff0c;macOS和Linux上运行。 功能特点 比较文件夹、文件 一、随时随地访问数据 Beyond Compare 是敏捷的。 我们的虚拟文件系统以透明的方式将您连接到您的数据…

Stable Diffusion实操示例

一、负向提示词 解决问题&#xff1a;生成的图片存在瑕疵&#xff0c;比如多只眼睛、多只手指等情况。通过embeddings可以将避免一些常用的不好结果。 方法&#xff1a;从https://civitai.com/?utm_sourcenettsz.com 中下载负向提示词的embeddings模型&#xff0c; EasyNeg…

SOLIDWORKS 2023修复遗漏配合参考及装配体磁力配合

1、修复遗漏的配合参考 ① 为面、边线、平面、轴和点的参考修复遗漏的配合参考 ② 位于与遗漏的参考相同的位置和方向的零部件上选择参考&#xff0c;可修复零 部件遗漏的参考 ③ 包含多个遗漏的配合参考的模型&#xff0c;右键单击配合 文件夹&#xff0c;然后单击自动修复…

AI Expo 2023 | 图技术激活数据资产主题论坛线下报名限时开放!

洞察关联数据 创造无限可能 图技术激活数据资产主题论坛 将于2023年6月25日在苏州召开。 大会背景 本次图技术激活数据资产论坛&#xff0c;由苏州市大数据服务中心协会主办、浙江创邻科技有限公司承办&#xff0c;苏州市计算机学会、苏州市大数据和人工智能产业联盟协办&…

(五) ElasticSearch 数据类型和文档CRUD操作

1.ES数据类型 官方文档地址&#xff1a;https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-types.html#_complex_datatypes 核心数据类型&#xff08;Core Data Types&#xff09;&#xff1a; 核心数据类型是 Elasticsearch 最基本和常用的数据类型…

DataX 3.0 在Windows下基于MySQL做数据迁移示例

在 Windows 安装 Datax&#xff1a; Datax 官网&#xff1a;https://github.com/alibaba/DataX 环境要求&#xff1a; 1&#xff1a;JDK&#xff08;1.8以上&#xff0c;推荐1.8&#xff0c;并配置好环境变量&#xff09; 2&#xff1a;Python&#xff08;网上推荐Python2.…