MVC、MVP、MVVM结合案例详解-附Demo

2024-05-08 22:48

本文主要是介绍MVC、MVP、MVVM结合案例详解-附Demo,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

    本篇以登陆模块功能详解MVC、MVP、MVVM的优缺点及使用。

目录

一、MVC

1.概念

2.总结

二、MVP

 1.概念

2.总结

三、MVVM

1.概念

2.Android Data Binding

2.1 布局和绑定表达式

2.2 在子线程中更新View

2.3 实现控件TextView的点击事件

3.MVVM核心

一、MVC

1.概念

MVC全名 Model View Controller

模型(model-视图(view-控制器(controller

M是指业务模型 V是指用户界面  C则是控制器

2.总结

其中 View 层其实就是程序的 UI 界面,用于向用户展示数据以及接收用户的输入

Model 层就是 JavaBean 实体类,用于保存实例数据

Controller 控制器用于更新 UI 界面和数据实例

       弊端:Activity既是C又是V,既有显示UI界面,又有登陆操作。所有的代码都是在MainActivity。见Demo app。

二、MVP

 1.概念

MVP是一种经典的模式

M代表Model  V代表View   P则是PresenterModelView之间的桥梁)

2.总结

MVP模式的核心思想

Activity中的UI逻辑抽象成View接口,把业务逻辑抽象成Presenter接口Model类还是原来的Model

作用

1.分离视图逻辑和业务逻辑,降低耦合

2.Activity只处理生命周期的任务,代码简洁

3.视图逻辑和业务逻辑抽象到了ViewPresenter中,提高阅读性

4.Presenter被抽象成接口,可以有多种具体的实现

5.业务逻辑在Presenter中,避免后台线程引用Activity导致内存泄漏

分析

1.建立3个包 model、view、Presenter分别存放对应的模型、视图、控制层。

2.Model

      定义用户名、密码,构造方法和一些set、get方法。

3.View

     UI逻辑抽象成View接口: view中UI逻辑有吐司、登陆成功或失败提示,需要定义在接口中。

4.Presenter

     业务逻辑抽象成Presenter接口:Presenter中业务逻辑有绑定和解绑View,登陆操作,需要定义在接口中。

5.实现

     在Activity和Presenter定义类,实现上述对应接口。

6.在MainActivity View中调用P接口。

7.如果有多个Activity,需要抽取共同的方法到Base接口。 要使用泛型

三、MVVM

1.概念

MVVM模式包含三个部分

-Model代表基本的业务逻辑

-View显示内容

-ViewModel将前面两者联系在一起

 

2.Android Data Binding

l2015I/O大会上谷歌介绍了一个非常NB的工具,该工具可以将View和一个对象的field绑定,当field更新的时候,framework将收到通知,然后View自动更新。

lData Binding官方原生支持MVVM模型可以让我们在不改变现有代码的框架下,非常容易的使用这些新特性。

2.1 布局和绑定表达式

(1)首先在app模块的build.gradle中加上几行代码就可以了。

android {…dataBinding {enabled = true}
}
插入代码前
插入代码前
插入代码后

   对比上述两个图发现添加代码后运行后会自动生成BR.class这个类。

   (2)布局文件这样写

<?xml version="1.0" encoding="utf-8"?>
<layoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"><data><variablename="user"type="m.cyh.com.mvvm.User"/></data><LinearLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context=".MainActivity"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@{user.userName}" /></LinearLayout>
</layout>

数据中的user变量描述了可以在该布局中使用的属性。

        <variablename="user"type="m.cyh.com.mvvm.User"/>

布局中的表达式使用“@ {}”语法写入属性。这里,TextView文本被设置为用户变量的userName属性:

        <TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@{user.userName}" />

(3)数据对象

一个普通的对象用于描述User实体:

public class User {private String userName;}

在数据绑定中,访问@{user.userName},那么默认就会访问同名的属性userName,或对应的getUserName方法。

(4)绑定数据

默认情况下,绑定类将基于布局文件的名称来产生 
       如布局文件为main_activity.xml,这样生成的类是 MainActivityBinding 
       如下设置Activity的contentView:

    @Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);
//        setContentView(R.layout.activity_main);//没有通过ID找到控件,只是对field进行操作就可以改变view的值ActivityMainBinding binding = DataBindingUtil.setContentView(MainActivity.this, R.layout.activity_main);final User user = new User();user.userName.set("dahai");binding.setUser(user);}

2.2 在子线程中更新View

如果在子线程直接user.setUserName("helloworld");会发现View并没有改变。那就是FrameWork并未收到通知,看文档发现需要用到可观察数据对象。

比较简单的一种方法是把User实体类变量类型改变为

public class User {public ObservableField<String> userName = new ObservableField<>();
}

使用get或set来获取和设置属性值。

    @Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);
//        setContentView(R.layout.activity_main);//没有通过ID找到控件,只是对field进行操作就可以改变view的值ActivityMainBinding binding = DataBindingUtil.setContentView(MainActivity.this, R.layout.activity_main);final User user = new User();user.userName.set("dahai");binding.setUser(user);new Thread(new Runnable() {@Overridepublic void run() {SystemClock.sleep(2000);user.userName.set("helloword!");}}).start();}

     运行后会发现:如下在子线程中更新View,FrameWork收到通知后会自动更新View。

2.3 实现控件TextView的点击事件

首先在TextView中添加属性。

        <TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@{user.userName}"android:onClick="@{user.userOnClick}"/>

在User类中实现点击事件方法。

    //点击TextView时弹出Logpublic void userOnClick(View view){Log.e("********User*******",userName.get());}

      点击TextView就会打印出日志Log。

3.MVVM核心

MVVM模式中,一个ViewModel和一个View匹配,它没有MVP中的IView接口,而是完全的和View绑定,所有View中的修改变化,都会自动更新到ViewModel中,同时ViewModel的任何变化也会自动同步到View上显示。

1.在build.gradle配置databinding。

2.首先新建三个包,model、view、viewmodel。在xml中更改layout。

3.viewmodel是负责M到V层,V层到M层。在viewmodel中新建MainViewModel类完成这个功能。其中包括从EtidText中拿到输入数据和点击事件。

/**
*负责M到V层,V到M层
*@author dahaiChang
*created at 2019/9/5 20:45
*/
public class MainViewModel {private String userName;private String psd;private Context mContext;public MainViewModel(Context context){this.mContext = context;}//从EditText拿到userNamepublic TextWatcher userNameChangeListener(){return new TextWatcher() {@Overridepublic void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {}@Overridepublic void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {userName = charSequence.toString();}@Overridepublic void afterTextChanged(Editable editable) {}};}//从EditText拿到psdpublic TextWatcher psdChangeListener(){return new TextWatcher() {@Overridepublic void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {}@Overridepublic void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {psd = charSequence.toString();}@Overridepublic void afterTextChanged(Editable editable) {}};}//登陆点击实现public void login(View view){if (!TextUtils.isEmpty(userName) && !TextUtils.isEmpty(psd)){if (userName.equals("dahai") && psd.equals("123456")){Toast.makeText(mContext,"登陆成功!",Toast.LENGTH_LONG).show();}else {Toast.makeText(mContext,"账号或密码错误!",Toast.LENGTH_LONG).show();}}else {Toast.makeText(mContext,"账号或密码输入不能为空!",Toast.LENGTH_LONG).show();}}
}

本文Demo下载地址:https://github.com/dahaiChang/MVC_MVP_MVVM

这篇关于MVC、MVP、MVVM结合案例详解-附Demo的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/971662

相关文章

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

Hadoop企业开发案例调优场景

需求 (1)需求:从1G数据中,统计每个单词出现次数。服务器3台,每台配置4G内存,4核CPU,4线程。 (2)需求分析: 1G / 128m = 8个MapTask;1个ReduceTask;1个mrAppMaster 平均每个节点运行10个 / 3台 ≈ 3个任务(4    3    3) HDFS参数调优 (1)修改:hadoop-env.sh export HDFS_NAMENOD

性能分析之MySQL索引实战案例

文章目录 一、前言二、准备三、MySQL索引优化四、MySQL 索引知识回顾五、总结 一、前言 在上一讲性能工具之 JProfiler 简单登录案例分析实战中已经发现SQL没有建立索引问题,本文将一起从代码层去分析为什么没有建立索引? 开源ERP项目地址:https://gitee.com/jishenghua/JSH_ERP 二、准备 打开IDEA找到登录请求资源路径位置

深入探索协同过滤:从原理到推荐模块案例

文章目录 前言一、协同过滤1. 基于用户的协同过滤(UserCF)2. 基于物品的协同过滤(ItemCF)3. 相似度计算方法 二、相似度计算方法1. 欧氏距离2. 皮尔逊相关系数3. 杰卡德相似系数4. 余弦相似度 三、推荐模块案例1.基于文章的协同过滤推荐功能2.基于用户的协同过滤推荐功能 前言     在信息过载的时代,推荐系统成为连接用户与内容的桥梁。本文聚焦于

OpenHarmony鸿蒙开发( Beta5.0)无感配网详解

1、简介 无感配网是指在设备联网过程中无需输入热点相关账号信息,即可快速实现设备配网,是一种兼顾高效性、可靠性和安全性的配网方式。 2、配网原理 2.1 通信原理 手机和智能设备之间的信息传递,利用特有的NAN协议实现。利用手机和智能设备之间的WiFi 感知订阅、发布能力,实现了数字管家应用和设备之间的发现。在完成设备间的认证和响应后,即可发送相关配网数据。同时还支持与常规Sof

【区块链 + 人才服务】可信教育区块链治理系统 | FISCO BCOS应用案例

伴随着区块链技术的不断完善,其在教育信息化中的应用也在持续发展。利用区块链数据共识、不可篡改的特性, 将与教育相关的数据要素在区块链上进行存证确权,在确保数据可信的前提下,促进教育的公平、透明、开放,为教育教学质量提升赋能,实现教育数据的安全共享、高等教育体系的智慧治理。 可信教育区块链治理系统的顶层治理架构由教育部、高校、企业、学生等多方角色共同参与建设、维护,支撑教育资源共享、教学质量评估、

客户案例:安全海外中继助力知名家电企业化解海外通邮困境

1、客户背景 广东格兰仕集团有限公司(以下简称“格兰仕”),成立于1978年,是中国家电行业的领军企业之一。作为全球最大的微波炉生产基地,格兰仕拥有多项国际领先的家电制造技术,连续多年位列中国家电出口前列。格兰仕不仅注重业务的全球拓展,更重视业务流程的高效与顺畅,以确保在国际舞台上的竞争力。 2、需求痛点 随着格兰仕全球化战略的深入实施,其海外业务快速增长,电子邮件成为了关键的沟通工具。

6.1.数据结构-c/c++堆详解下篇(堆排序,TopK问题)

上篇:6.1.数据结构-c/c++模拟实现堆上篇(向下,上调整算法,建堆,增删数据)-CSDN博客 本章重点 1.使用堆来完成堆排序 2.使用堆解决TopK问题 目录 一.堆排序 1.1 思路 1.2 代码 1.3 简单测试 二.TopK问题 2.1 思路(求最小): 2.2 C语言代码(手写堆) 2.3 C++代码(使用优先级队列 priority_queue)

【区块链 + 人才服务】区块链集成开发平台 | FISCO BCOS应用案例

随着区块链技术的快速发展,越来越多的企业开始将其应用于实际业务中。然而,区块链技术的专业性使得其集成开发成为一项挑战。针对此,广东中创智慧科技有限公司基于国产开源联盟链 FISCO BCOS 推出了区块链集成开发平台。该平台基于区块链技术,提供一套全面的区块链开发工具和开发环境,支持开发者快速开发和部署区块链应用。此外,该平台还可以提供一套全面的区块链开发教程和文档,帮助开发者快速上手区块链开发。

K8S(Kubernetes)开源的容器编排平台安装步骤详解

K8S(Kubernetes)是一个开源的容器编排平台,用于自动化部署、扩展和管理容器化应用程序。以下是K8S容器编排平台的安装步骤、使用方式及特点的概述: 安装步骤: 安装Docker:K8S需要基于Docker来运行容器化应用程序。首先要在所有节点上安装Docker引擎。 安装Kubernetes Master:在集群中选择一台主机作为Master节点,安装K8S的控制平面组件,如AP