[转载]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开发中,很多人经常会头疼于 ...
随机推荐
- Codeforces Round #642 (Div. 3)
比赛链接:https://codeforces.com/contest/1353 A - Most Unstable Array 题意 构造大小为 $n$,和为 $m$ 的非负数组 $a$,使得相邻元 ...
- Codeforces Round #642 (Div. 3) D. Constructing the Array (优先队列)
题意:有一个长度为\(n\)元素均为\(0\)的序列,进行\(n\)次操作构造出一个新序列\(a\):每次选择最长的连续为\(0\)的区间\([l,r]\),使得第\(i\)次操作时,\(a[\fra ...
- 80x86/Pentium微机原理及接口技术-微处理器-学习笔记
80x86/ Pentium微机原理及接口技术 1. 计算机基础... 1 1.1常用术语... 1 1.2计算机中数与编码的表示方法... 1 1.2.1进制表示及进制转换... 1 1.2 ...
- GitHub Actions 支持 "skip ci" 了
GitHub Actions 支持 "skip ci" 了 Intro GitHub Actions 作为 GitHub 官方的 CI 支持,很多开源项目已经在使用 Actions ...
- M1 MacBook安装Homebrew
在装载M1芯片的MacBook产品上,默认是不带有homebrew这款包管理工具的,具体原因官方解释为适配问题,原有的homebrew无法与silicon Mac机型匹配.但是这并不意味着我们不可以在 ...
- Django服务器布置(Ubuntu+uwsgi+nginx+Django)
一.安装Python apt install python3 二.安装pip apt install python3-pip 三.创建目录 创建虚拟服务目录 mkdir -p /data/env 创建 ...
- 二进制安装kubernetes(一) 环境准备及etcd组件安装及etcd管理软件etcdkeeper安装
实验环境: 架构图: 主机环境: 操作系统:因docker对内核需要,本次部署操作系统全部采用centos7.6(需要内核3.8以上) VM :2C 2G 50G * 5 PS:因后面实验需要向k8 ...
- JVM进阶篇
class Person { private String name = "Jack"; private int age; private final double salar ...
- sqlmap在https情况下的一个错误
对于https网站,使用sqlmap可能会出现如下错误.使用–force-ssl无效. https证书有问题 方法 本地建立proxy.php,内容为 <?php $url = "ht ...
- How to using PyPI publish a Python package
How to using PyPI publish a Python package PyPI & Python package https://pypi.org/ main make a f ...