Android MVC和MVP架构的详解

原创 2017年10月31日 21:10:32
MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,
用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面
及用户交互的同时,不需要重新编写业务逻辑。其中
M层:处理数据,业务逻辑等;
V层:处理界面的显示结果;
C层:起到桥梁的作用,来控制V层和M层通信以此来达到分离视图、显示和业务逻辑层。


在Android中使用如下图:


View 层:在开发中xml文件就是我们的View布局,一般情况下我们都会用xml来实现我们的布局,相对的节省性能的消耗。但是也有一些比较特殊、比较复杂的需求我们需要用到自定义view,其实自定义View也是属于View,这是比较少的情况,正常我们都会用xml来实现View的。

Controller层:控制层,其实Android已经默认给我们提供了Controller,就是Activity和Fragment,仔细一想就可以明白,用户在View层做出请求的操作,Activity和Fragment就会对用户做出的请求做出相应的处理,得到相应的结果之后,再呈现给用户。
其实对于Activity和Fragment人们有时会认为它是属于View层的。的确,在MVC的View层中的xml布局是不会改变的,而当用户在操作的时候我们的View总要做出相应的改变,而有些改变单单是xml是没办法做到的,所以在Activity和Fragment这个Controller层中多多少少都会有View层的东西。但是在Activity和Fragment中总归还是Controller层的代码占绝大多数,因此我们还是把它归类为Controller层。


Model层:Android中除了View和Controller,剩下的绝大多数来说都是Model层的东西了。其实Model一般不会被定义得很死,Model本身就数据和业务逻辑有关的,而不同的需求当然是有不同的数据和业务逻辑的,其中数据模型(javaBean)、数据的存取、网络的操作、以及一些耗时的任务等等。

项目结构:


接下来Demo演示,数据模型类:

public class Person {
	private int per_id;
	private String username;
	private String sex;
	private int age;

	public Person(int per_id, String username, String sex,
			int age) {
		this.per_id = per_id;
		this.username = username;
		this.sex = sex;
		this.age = age;
	}

	public int getPer_id() {
		return per_id;
	}

	public void setPer_id(int per_id) {
		this.per_id = per_id;
	}

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}


	public String getSex() {
		return sex;
	}

	public void setSex(String sex) {
		this.sex = sex;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	@Override
	public String toString() {
		return "Person->[per_id=" + per_id + ", username=" + username
				+ ", sex=" + sex + ", age=" + age
				+ "]";
	}

}

获取数据侦听:

public interface GetDataListener {
	void onGetDataSuccess(Person person);

	void onGetDataError(String errmessage);
}

获取数据接口:

public interface GetData {
	void getShopsData(GetDataListener getDataListener);
}

获取数据:

public class GetDataImplement implements GetData {

	@Override
	public void getShopsData(GetDataListener getDataListener) {
		Person person = new Person(1, "layne", "male", 18);
		if(person!=null){
			getDataListener.onGetDataSuccess(person);
		}else{
			getDataListener.onGetDataError("请求失败");
		}
	}

}

控制层:

public class MainActivity extends ActionBarActivity implements GetDataListener,
		OnClickListener {
	private Button bt_request;
	private TextView tv_content;
	private GetData getData;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		InitView();

	}

	private void InitView() {
		bt_request = (Button) findViewById(R.id.bt_request);
		tv_content = (TextView) findViewById(R.id.tv_content);

		bt_request.setOnClickListener(this);

		getData = new GetDataImplement();
	}

	@Override
	public void onClick(View view) {
		switch (view.getId()) {
		case R.id.bt_request:
			getData.getShopsData(this);
			break;
		}

	}

	@Override
	public void onGetDataSuccess(Person person) {
		showData(person);

	}

	@Override
	public void onGetDataError(String errmessage) {
		Toast.makeText(this, errmessage, Toast.LENGTH_SHORT).show();

	}

	// 控制层将Model层里面的数据呈现到View层
	private void showData(Person person) {
		tv_content.setText(person.toString());
	}

}

视图层:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.itman.mvcdemo1.controller.MainActivity" >

    <Button
    android:id="@+id/bt_request"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="20dp"
    android:text="请求数据" />
    
   <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="20dp"
        android:layout_marginRight="20dp"
        android:orientation="horizontal" >

        <TextView
            android:id="@+id/tv_content"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="请求的内容" />

    </LinearLayout>
    
</LinearLayout>

运行结果:

     

总结:

MVC的优点:
很明显如果要求不高,我们平时的小项目就是一般的MVC,这个框架学习成本低,理解起来非常容易,对UI层与业务层进行分离,对Model层和数据方面做一下分层和封装,就是一个扩展性不错,挺清晰的MVC开发框架了。

但是缺点也是很明显的:
随着我们的业务壮大起来,需求越来越多,那么Activity和Fragment的代码就会越来越多,有的甚至夸张到一个activity就有几千行代码的,就会变得越来越臃肿,当我们维护和改变需求的时候是非常耗时间和精力的。这个就是MVC的缺点。



MVP架构

根据上文一开始MVC架构,项目随着需求不断增多,业务逻辑更加的复杂,我们的activity和fragment的代码也是越来越臃肿的。这时的activity和fragment理解和维护起来科室非常的费事费力,很痛苦的一件事,相信我们程序员都不太愿意去面对这样的情况的。这时MVP就应运而生,原先MVC中的Controller层activity或fragment将抽出控制层的代码,剩余的归类为View层,也就是说activity和fragment在MVP中是属于View层的,而被抽出的控制层代码成为了新的一员Presenter。
MVP的各个职责:
View层:
对应于Activity,负责View的绘制以及与用户交互,处理界面的显示结果
Model层:处理数据,业务逻辑等
Presenter层:负责完成View于Model间的交互

MVP其实就是减少了Activity和fragment的职责,减少了Activity和fragment的代码,将繁杂的逻辑代码交给了Presenter,相对应的好处就是耦合度更加的低,更方便单元测试了,同时借用两张图来说明变化(图片出处):


转变为:



MVC和MVP的区别(图片出处):根据图中我们可以知道在MVC中Model层是可以和View层交互的,但是在MVP中Model层和View层的交互是完全交给了Presenter的


接下来我们根据上面的MVC的Demo,将之修改成MVP架构的Demo

项目结构



数据模型:

public class Person {
	private int per_id;
	private String username;
	private String sex;
	private int age;

	public Person(int per_id, String username, String sex,
			int age) {
		this.per_id = per_id;
		this.username = username;
		this.sex = sex;
		this.age = age;
	}

	public int getPer_id() {
		return per_id;
	}

	public void setPer_id(int per_id) {
		this.per_id = per_id;
	}

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}


	public String getSex() {
		return sex;
	}

	public void setSex(String sex) {
		this.sex = sex;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	@Override
	public String toString() {
		return "Person->[per_id=" + per_id + ", username=" + username
				+ ", sex=" + sex + ", age=" + age
				+ "]";
	}

}

请求侦听:

public interface GetDataListener {
	void onGetDataSuccess(Person person);

	void onGetDataError(String errmessage);
}

Presenter接口:

public interface IGetDataPresenter {
	void getData(GetDataListener getDataListener);
	
	void clear();
}

Presenter:

public class GetDataPresenterCompl implements IGetDataPresenter {

	private IGetDataView getDataView;
	private Person person;

	public GetDataPresenterCompl(IGetDataView getDataView) {
		this.getDataView = getDataView;
	}

	@Override
	public void getData(GetDataListener getDataListener) {
		person = new Person(1, "layne", "male", 18);
		if (person != null) {
			getDataListener.onGetDataSuccess(person);
		} else {
			getDataListener.onGetDataError("请求失败");
		}
	}

	@Override
	public void clear() {
		getDataView.clearData();
	}

}

视图的接口:

public interface IGetDataView {
	
	void clearData();
}

Activity:

public class MainActivity extends ActionBarActivity implements IGetDataView,
		GetDataListener, OnClickListener {

	private Button bt_request, bt_clear;
	private TextView tv_content;
	
	private IGetDataPresenter getDataPresenter;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		InitView();
	}

	private void InitView() {
		bt_request = (Button) findViewById(R.id.bt_request);
		bt_clear = (Button) findViewById(R.id.bt_clear);
		tv_content = (TextView) findViewById(R.id.tv_content);

		bt_request.setOnClickListener(this);
		bt_clear.setOnClickListener(this);
		
		getDataPresenter = new GetDataPresenterCompl(this);
	}

	@Override
	public void onClick(View v) {
		switch (v.getId()) {
		case R.id.bt_request:
			getDataPresenter.getData(this);
			break;

		case R.id.bt_clear:
			getDataPresenter.clear();
			break;
		}

	}

	@Override
	public void onGetDataSuccess(Person person) {
		showData(person);

	}

	@Override
	public void onGetDataError(String errmessage) {
		Toast.makeText(this, errmessage, Toast.LENGTH_SHORT).show();

	}

	@Override
	public void clearData() {
		tv_content.setText("清空内容");

	}
	
	private void showData(Person person) {
		tv_content.setText(person.toString());
	}


}

最后是布局文件:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.itman.mvpdemo.view.MainActivity" >

    <Button
        android:id="@+id/bt_request"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="20dp"
        android:layout_marginRight="20dp"
        android:layout_marginTop="5dp"
        android:text="请求数据" />

    <Button
        android:id="@+id/bt_clear"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="20dp"
        android:layout_marginRight="20dp"
        android:layout_marginTop="5dp"
        android:text="清除数据" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="20dp"
        android:layout_marginRight="20dp"
        android:orientation="horizontal" >

        <TextView
            android:id="@+id/tv_content"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="请求的内容" />
    </LinearLayout>

</LinearLayout>

运行结果:

      

MVP的优点:
1.更加的降低了耦合度,使得Model层和View层的完全解耦
2.模块职责划分清楚,层次分明
3.Presenter一定程度下可以复用,一个Presenter可用于多个View,前提是View的改动不影响业务逻辑。
4.单元测试更加的方便


缺点:
1.层次分明的代价是额外的代码和类,这更加的增加了学习成本
2.如果Presenter过多地与特定的视图的联系过于紧密,一旦视图需要变更,那么Presenter也需要变更了。

版权声明:欢迎以任何形式转载,但请注明作者和出处

android中MVC,MVP和MVVM三种模式详解析

我们都知道,android本身就采用了MVC模式,model层数据源层我们就不说了,至于view层即通过xml来体现,而 controller层的角色一般是由activity来担当的。虽然我们项目用到...
  • u013320868
  • u013320868
  • 2016年08月11日 11:36
  • 849

Android架构之MVC,MVP与MVVM

概述MVP(Model-View-Presenter)是传统MVC(Model-View-Controller)在Android开发上的一种变种、进化模式。主要用来隔离UI、UI逻辑和业务逻辑、数据,...
  • wbwjx
  • wbwjx
  • 2016年06月09日 23:09
  • 1397

Android中MVC、MVP、MVVM详解

前言 今天有时间就刚好有想写关于这几个名词,对于我来说,其实这么多名词、思想归根到底就是要根据项目实际、人员配置来做合理优化,既不能纸上谈兵、又不能畏惧不前,那么合理分阶段架构和完善代码才是关键,本...
  • Apple_hsp
  • Apple_hsp
  • 2016年03月22日 15:19
  • 3607

MVC与MVP架构特点与区别-android

1.MVC的基本介绍 MVC全称是Model - View - Controller,是模型(model)-视图(view)-控制器(controller)的缩写。MVC是一种框架模式而非设计模式...
  • ShareUs
  • ShareUs
  • 2016年05月23日 14:18
  • 25699

Android App的设计架构:MVC,MVP,MVVM与架构经验谈

Android App的设计架构:MVC,MVP,MVVM与架构经验谈 周鸿博 发布于 3 个月前 0评论 1798浏览转载地址:http://www.tianmaying.com/tutori...
  • lovingkid
  • lovingkid
  • 2016年03月17日 22:46
  • 1974

浅谈Android中MVP模式与MVC模式的区别

理论内容转载自:http://blog.csdn.net/lmj623565791/article/details/46596109一、概述对于MVP(Model View Presenter),大多...
  • uniquemei
  • uniquemei
  • 2016年06月27日 18:01
  • 6057

Android 开发的两种框架 MVC和MVP 的简单分析

在常见的android开发框架,有MVC和MVP两种,下面我来分别简单介绍一下。 一、MVC框架 MVC,即model(模型),view(视图),controler(控制器)三个单词的简称。 其中Mo...
  • muMUXiong_
  • muMUXiong_
  • 2016年06月27日 14:11
  • 1369

浅谈Android中的MVC与MVP模式

使用MVC或者MVP模式会增加很多的类,但是确可以让代码结构变得清晰,方便了后期维护拓展方便。把数据层跟视图层分离,处理事务的逻辑单独的放在一个类中,让Activity仅仅具有展示功能。 下面我们就M...
  • a516972602
  • a516972602
  • 2016年05月10日 11:45
  • 2271

框架模式MVC与MVP的区别

MVC和MVP到底有什么区别呢? MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务...
  • Carry_Code
  • Carry_Code
  • 2016年07月03日 21:18
  • 561

【编程素质】三层架构、MVC、MVP、MVVM

1,对比 1)MVC和三层架构 是完全不同的2种设计规范。但核心一致:分层,解耦。 2,MVC (Model View Controller) 工作原理:当用户出发事件的时...
  • SunshineTan
  • SunshineTan
  • 2017年07月12日 11:53
  • 421
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Android MVC和MVP架构的详解
举报原因:
原因补充:

(最多只允许输入30个字)