[转载]Android MVC,MVP和MVVM 思想&例子
在Android开发中,常采用 MVC(Model-View-Controller)或者MVP(Model-View-Presenter) 等框架模式。设计如图

可以看出,在 MVC 框架中,请求流程如下:
- View接受用户的请求
- View传递请求给Controller
- Controller操作Model进行数据更新
- Model通知View变化
- View根据更新的数据做出显示
而MVP框架中,请求流程如下:
- View 接受用户请求
- View 传递请求给Presenter
- Presenter做逻辑处理,修改Model
- Model 通知Presenter数据变化
- Presenter 更新View
相比于MVC,MVP则使用Presenter解除了View与Model的耦合,Presenter将Model的变化返回给View。
举个栗子
小明需要开发一个功能,当点击“find student id”按钮时,可以查询到他自己的学号。

对于MVC 实现,应该是这样的:
1.先实现一个 model,需要有通知View更新的能力,当model加载成功,如从db、获取后,需要告知View:
public class StudentModel {
String mId;
WelcomeActivity mActivity;
public StudentModel (WelcomeActivity activity) {
this.mActivity = activity;
}
public void loadModel (){
//search from db or intent
mId = "1201030018";
mActivity.updateUI(this);
}
}
2.Controller : 我们为了更好的理解MVC,将Activity进行了拆解。提取了一个简单的Controller
public class WelcomeController {
WelcomeActivity mActivity;
StudentModel mStudent;
WelcomeController (WelcomeActivity activity) {
this.mActivity = activity;
}
public void loadData (){
mStudent = new StudentModel(mActivity);
mStudent.loadModel();
}
}
- View : View需要发出点击事件,并且传递给Controller,同时需要根据Model更新UI:
public class WelcomeActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
//省略
final WelcomeController controller = new WelcomeController(this);
mFindBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
controller.loadData();
}
});
}
public void updateUI (StudentModel model) {
mID.setText(model.mId);
}
}
调用链是:
View:OnClick ->
Controller:loadData->
Model:loadModel->
View:updateUI
这里为了更明显的表明意图,将Activity单纯的看做一个View。
MVP 改写
同样的例子,我们使用MVP进行改写
- 我们需要先对Model进行封装,当loadModel后,不直接通知View更新,而是通知监听方(Presenter):
public class StudentModel {
String mId;
OnGetListener mListener;
public StudentModel (OnGetListener listener) {
this.mListener = listener;
}
public void loadModel (){
//search from db or intent
mId = "1201030018";
if (mListener != null) {
mListener.onSuccess(this);
}
}
interface OnGetListener {
void onSuccess (StudentModel student);
}
}
2.再定义Presenter ,接收到来自View的操作命令后,进行逻辑处理,处理Model,修改完成后 通知View进行修改。
public class WelcomePresenter {
WelcomeActivity mActivity;
StudentModel mStudent;
WelcomePresenter (WelcomeActivity activity) {
this.mActivity = activity;
}
public void loadData (){
mStudent = new StudentModel(new StudentModel.OnGetListener() {
@Override
public void onSuccess(StudentModel student) {
mActivity.updateUI(student);
}
});
}
}
3.对于View,操作方式只是修改了持有的对象 WelcomeController->WelcomePresenter,其他保持不变。
这时调用流程变成了:
View:OnClick ->
Presenter:loadData->
Model:loadModel->
Presenter:onSuccess>
View:updateUI
我们将View的数据更新 从Model->View,转变成了Presenter->View,解除了View和Model的耦合。
mvvm
早些年微软WPF提出的数据绑定系统与Presentation Model相结合的做法,能使开发人员将View和逻辑分离,称之Model-View-ViewModel(MVVM)。
在Android 借助Google提出的 DataBinding 框架完成 双向绑定操作。
DataBinding用法可以参考: https://developer.android.com/topic/libraries/data-binding/index.html
调用链路如下:

可以看到,在MVVM框架中,除了将 Presenter 换成了 ViewModel 外,请求流程都和MVP类似,只是在最后一步中,由于View与ViewModel使用了双向绑定,两者的交互通过Data Binding 完成。如此使得View和控制模块的耦合更加降低,减轻了视图的压力。
还是那个栗子
我们引入Data Binding解决这个问题。
- 把Controller\Presenter扔掉,先写一个ViewModel
这个VM的概念是一个和视图相关的模型,因此可以和DAO相关的模型不一样,因为我们只需要展示student id的数据以及click事件,以及loadData行为,用来从Model中获取数据,于是我们实现了一个VM :
这里我们需要遵循Data Binding的语法,如继承自BaseObservable,数据更新后调用
notifyChange方法等。
public class StudentViewModel extends BaseObservable{
String studentID;
View.OnClickListener btnListener;
//省略get set
public StudentViewModel() {
btnListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
loadData();
}
};
}
public void loadData() {
StudentModel model = new StudentModel(new StudentModel.OnGetListener() {
@Override
public void onSuccess(StudentModel student) {
setStudentID(student.mId);
}
});
model.loadModel();
}
}
- 接着使用databinding语法 对 xml 进行数据绑定,我们将 Click事件、输出结果都绑定到VM上。
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable name="userVM" type="com.moon.coderread.StudentViewModel"/>
</data>
<LinearLayout
//省略
<TextView
android:id="@+id/id"
android:layout_width="match_parent"
android:layout_height="20dp"
android:text="@{userVM.studentID}"/>
<Button
android:id="@+id/findBtn"
android:onClick="@{userVM.btnListener}"
android:text="find Student ID"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
</layout>
- 最后在
View(Activity)中引入VM :
public class WelcomeActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
ActivityWelcomeBinding binding = DataBindingUtil.setContentView(this,R.layout.activity_welcome);
final StudentViewModel studentViewModel = new StudentViewModel();
binding.setUserVM(studentViewModel);
}
}
这样就完成了最基本的MVVM 栗子。
现在我们的Activity看起来很清爽,不用再处理Click事件、以及updateUI了。
总结
各种MV+X模式的发展,实质上就是将Model与View之间以一种低耦合、低成本的方式进行控制。从Presenter到ViewModel的转变,借助了Data Binding的方式实现了双向的数据绑定,减少了视图模块和控制模块的耦合。随着Google Data Binding技术的不断更新完善,相信MVVM模式将在Android平台下应用得更加广泛。
栗子仅仅是
上面仅仅是以最简单的方式来描述了一下 MV+X模式的实现流程,在实践项目里场景会复杂数倍。
作者:andChen
链接:https://www.jianshu.com/p/9df92995ee26
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
[转载]Android MVC,MVP和MVVM 思想&例子的更多相关文章
- Android MVC MVP
从.NET的宠物商店到Android MVC MVP 1 一些闲话 记得刚进公司的时候,我们除了做常规的Training Project外,每天还要上课,接受各种技术培训和公司业务介绍.当时第一次 ...
- MVC MVP 和 MVVM的图示
一直对于这些什么MVC MVP 和 MVVM都是云里雾里的 完全分不清楚 感觉jq上也没怎么用过,理解也很片面,画几张图也许能够大体分清他们之间的区别. 1.MVC(Model-View-Contro ...
- android MVC && MVP && MVVM分析和对比
相关:http://www.cnblogs.com/wytiger/p/5305087.html 出处http://blog.csdn.net/self_study,对技术感兴趣的同鞋加群544645 ...
- Android MVC,MVP,MVVM模式入门——重构登陆注册功能
一 MVC模式: M:model,业务逻辑 V:view,对应布局文件 C:Controllor,对应Activity 项目框架: 代码部分: layout文件(适用于MVC和MVP两个Demo): ...
- Android MVC MVP MVVM (三)
MVVM Model-View-ViewModel的简写 在MVP基础上实现数据视图的DataBinding,数据变化,视图自动变化,反之也成立. DataBinding 启用DataBinding ...
- Android MVC MVP MVVM (二)
MVP模型 View主要是Activity,Fragment MVP和MVC的差别 1.Model和View不再直接通信,通过中间层Presenter来实现. 2.Activity的功能被简化,不再充 ...
- Android MVC MVP MVVM (一)
示例效果 一共三个控件,EditText,Button,TextView 成功显示账号信息,查询失败显示错误信息. <?xml version="1.0" encoding= ...
- 从.NET的宠物商店到Android MVC MVP
1 一些闲话 记得刚进公司的时候,我们除了做常规的Training Project外,每天还要上课,接受各种技术培训和公司业务介绍.当时第一次知道QA和SQA的区别.Training Project时 ...
- Android App的设计架构:MVC,MVP,MVVM与架构经验谈
相关:http://www.cnblogs.com/wytiger/p/5996876.html 和MVC框架模式一样,Model模型处理数据代码不变在Android的App开发中,很多人经常会头疼于 ...
随机推荐
- ACdream1414 Geometry Problem
Problem Description Peter is studying in the third grade of elementary school. His teacher of ...
- 虚拟机linux操作系统上安装vmwareTools
当你安装过操作系统后,你就可以在虚拟机上找到这个画面,在管理里面有一个安装VMwareTools这就是我们的目标,打开后就直接点击下载并安装就好了 当下载完成后在虚拟机下面就会出现这个东西,他的意思就 ...
- kubernetes实战-交付dubbo服务到k8s集群(六)使用blue ocean流水线构建dubbo-consumer服务
我们这里的dubbo-consumer是dubbo-demo-service的消费者: 我们之前已经在jenkins配置好了流水线,只需要填写参数就行了. 由于dubbo-consumer用的gite ...
- Seq2Seq原理详解
一.Seq2Seq简介 seq2seq 是一个Encoder–Decoder 结构的网络,它的输入是一个序列,输出也是一个序列.Encoder 中将一个可变长度的信号序列变为固定长度的向量表达,Dec ...
- codeforces 1076E Vasya and a Tree 【dfs+树状数组】
题目:戳这里 题意:给定有n个点的一棵树,顶点1为根.m次操作,每次都把以v为根,深度dep以内的子树中所有的顶点(包括v本身)加x.求出最后每个点的值为多少. 解题思路:考虑到每次都只对点及其子树操 ...
- Leetcode(868)-二进制间距
给定一个正整数 N,找到并返回 N 的二进制表示中两个连续的 1 之间的最长距离. 如果没有两个连续的 1,返回 0 . 示例 1: 输入:22 输出:2 解释: 22 的二进制是 0b10110 . ...
- c# xaml (1)
原文:https://www.wpf-tutorial.com/xaml/what-is-xaml/ vs2017 新建 wpf 项目,在解决方案里会自动创建MainWindow.xaml文件 1.新 ...
- C++ part6
C++源文件从文本到可执行文件经历的过程 references: 一个C++源文件从文本到可执行文件经历的过程 C++源文件从文本到可执行文件经历的过程 gcc程序编译的静态链接和动态链接 保留中间过 ...
- html图片占位符插件holder.js
1.下载源码 下载链接:http://www.bootcdn.cn/holder/ 2.在HTML中引入holde.js <script src="holder-js-2.9.4\ho ...
- LeetCode 二叉树,两个子节点的最近的公共父节点
LeetCode 二叉树,两个子节点的最近的公共父节点 二叉树 Lowest Common Ancestor of a Binary Tree 二叉树的最近公共父亲节点 https://leetcod ...