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也需要变更了。

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

【架构设计】MVP与MVC,实现Android应用层开发

背景 之所以要谈这个话题是因为你在开发App时可能会发现,Activity担负的责任非常之重,如果站在MVC框架角度看自己开发的App,一般xml布局文件科Activity的setConte...

Android App的三种架构模式MVC,MVP和MVVM

Android App的三种架构模式MVC,MVP和MVVM

Android架构之MVC,MVP与MVVM

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

浅谈Android架构设计模式中MVC、MVP、MVVM

以下基于对三种模式已经熟悉所总结,不会介绍模式的基础概念,以下是自己结合其他人和自己实际开发中的经验对这些概念一些感悟。 Activity是V还是C 对于Activity属于V还是属于C这...
  • ourpush
  • ourpush
  • 2016年10月01日 22:16
  • 277

Android App 的设计架构:MVC、MVP、MVVM 的分析

MVC框架模式一样,Model模型处理数据代码不变在Android的App开发中,很多人经常会头疼于App的架构如何设计: 我的App需要应用这些设计架构吗? MVC,MVP等架构讲的是什么?区别是什...

Android App的架构设计:从VM、MVC、MVP到MVVM

随着Android应用开发规模的扩大,客户端业务逻辑也越来越复杂,已然不是简单的数据展示了。如同后端开发遇到瓶颈时采用的组件拆分思想,客户端也需要进行架构设计,拆分视图和数据,解除模块之间的耦合,提高...

Android三种常见软件架构MVC MVP MVVM

简析MVC MVP MVVM及区别   1、MVC: MVC,Model+View+Controller作为一种最为常规常见的设计模式,在Android开发历程初期被频繁使用。   设计原理: 一个指...

Android开发中逐步取代MVC的MVP架构知多少?

MVP

Android架构 - MVC与MVP

一. MVC在Android的开发过程中,每个层对应如下: Model层:对应Java Bean、数据库和网络请求等; View层:对应xml布局、自定义View或ViewGroup; C...

Android架构MVC,MVP讲解

周鸿博大神的,原文出处Android App的设计架构:MVC,MVP,MVVM与架构经验谈 和MVC框架模式一样,Model模型处理数据代码不变在Android的App开发...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Android MVC和MVP架构的详解
举报原因:
原因补充:

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