[框架模式]MVP应用架构模式

感谢《Android源码设计模式解析与实战》 何红辉 关爱民 著

MVP(Model View Presenter)目前在Android开发中越来越重要了,MVP能够有效地降低View复杂性,避免业务逻辑被塞进View中,使得View变成一个混乱的泥坑。MVP模式会解除View与Model的耦合,同时又带来了良好的可扩展性、可测试性,保证了系统的整洁性、灵活性。

可能对于简单的应用来说MVP稍显麻烦,各种各样的接口与概念,使得整个应用充斥着零散的接口,但是对于比较复杂的应用来说,MVP模式是一种良好的架构模式,它能够非常好地组织应用结构,使得应用变得灵活,拥抱变化。


MVP模式可以分离显示层和逻辑层,它们之间通过接口进行通信,降低耦合,理想化的MVP模式可以实现同一份逻辑代码搭配不同的显示界面,因为它们之间并不依赖于具体,而是依赖于抽象,这使得Presenter可以运用于任何实现了View逻辑接口的UI,使之具有更广泛的适用性,保证了灵活度。


MVP模式的三个角色:

1.Presenter——交互中间人

Presenter主要作为沟通View和Model的桥梁,它从Model层检索数据后,返回给View层,使得View和Model之间没有耦合,也将业务逻辑从View角色上抽离出来。

2.View——用户界面

View通常是指Activity、Fragment或者某个View控件,它含有一个Presenter成员变量。通常View需要实现一个逻辑接口,将View上的操作通过会转交给Presenter进行实现,最后,Presenter调用View逻辑接口将结果返回给View元素。

3.Model——数据的存取

对于一个结构化的App来说,Model角色主要是提供数据的存取功能。Presenter需要通过Model层存储、获取数据,Model就像一个数据仓库。更直白地说,Model是封装了数据库DAO或者网络获取数据的角色,或者两种数据获取方式的集合。



与MVC、MVVM的区别

1.MVC特点

1.用户可以向View发送指令,再由View直接要求Model改变状态。

2.用户也可以直接向Controller发送指令,再由Controller发送给View。

3.Controller起到事件路由的作用,同时业务逻辑都部署在Controller中。

MVC的耦合性还是相对较高的,View可以直接访问Model,导致3者之间构成回路,因此MVP与MVC的主要区别是,MVP中的View不能直接访问Model,需要通过Presenter发出请求,View与Model不直接通信


2.MVVM特点

MVVM与MVP非常相似,唯一的区别是VIew和Model进行双向绑定(data-binding),两者之间有一方发生变化则会反应到另一方上。而MVP与MVVM的主要区别则是,MVP中的View更新需要通过Presenter,而MVVM则不需要,因为View与Model进行了双向绑定,数据的修改会直接反应到View角色上,而View的修改也会导致数据的变更。此时,ViewModel角色需要做的只是业务逻辑的处理,以及修改View或者Model的状态。MVVM模式有点像ListView与Adapter、数据集的关系,这个Adapter就是ViewModel角色,它与View进行了绑定,又与数据集进行了绑定,当数据集合发生变化时,调用Adapter的notifyDataSetChanged之后View就直接更新,它们之间没有直接的耦合,使得ListView变得更为灵活。



注意

由于Presenter经常性的需要执行一些耗时操作,例如,请求网络数据,Presenter持有了Activity的强引用,如果在请求结束之前Activity被销毁了,那么由于网络请求还没有返回,导致Presenter一直持有Activity对象,使得Activity对象无法被回收,此时就发生了内存泄露。如何来解决这样的问题?

可以通过弱引用和Activity、Fragment的生命周期来解决这个问题,首先建立一个Presenter抽象,它是一个泛型类,泛型类型为View角色要实现的接口类型:

public abstract class BasePresenter<T> {
	protected Reference<T> mViewRef;//View接口类型的弱引用
	
	public void attachView(T view){
		mViewRef = new WeakReference<T>(view); //建立关联
	}
	
	protected T getView(){
		return mViewRef.get();
	}
	
	public boolean isViewAttached(){
		return mViewRef != null && mViewRef.get() != null;
	}
	
	public void detachView(){
		if(mViewRef != null){
			mViewRef.clear();
			mViewRef = null;
		}
	}
}
BasePresenter有4个方法,分别与View建立关联、解除关联、判断是否与View建立了关联、获取View。View类型通过BasePresenter的泛型类型传递进来,Presenter对这个View持有弱引用。通常情况下这个View类型应该是实现了某个特定接口的Activity或者Fragment等类型。

创建一个MVPBaseActivity基类,通过这个基类的生命周期函数来控制它与Presenter的关系;

public abstract class MVPBaseActivity<V,T extends BasePresenter<V>> extends Activity{
	protected T mPresenter; // Presenter对象
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		mPresenter = createPresenter();
		mPresenter.attachView((V)this);  //View 与Presenter建立关联
	}

	@Override
	protected void onDestroy() {
		super.onDestroy();
		mPresenter.detachView();
	}
	
	protected abstract T createPresenter();
}
MVPBaseActivity含有两个泛型参数,第一个是View接口类型,第二个是Presenter的具体类型,通过泛型参数,使得一些通用的逻辑可以被抽象到MVPBaseActivity类中。例如,在MVPBaseActivity的onCreate函数中,会通过createPresenter函数创建一个具体的Presenter,这个Presenter的类型就是BasePresenter<T>类型。构建Presenter之后调用attachView函数与Activity建立关联。而在onDestory函数中,则会与Activity解除关联,从而避免内存泄漏。有的人可能会有疑问,如果在onDestory中解除了对Activity的引用,那么就没有必要再用弱引用了。并不是在任何情况下Activity的onDestory都会被调用,一旦这种情况发生,弱引用也能够保证不会造成泄漏。而通过MVPBaseActivity的封装维护Presenter与View关联关系的代码,使得子类可以避免重复的代码。如:

public class DemoActivity extends MVPBaseActivity<ArticleViewInterface, ArticlePresenter> implements ArticleViewInterface{

	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		initViews();
		mPresenter.fetchArticles();
	}
	
	private void initViews() {
	}

	@Override
	protected ArticlePresenter createPresenter() {
		
		return null;
	}

	@Override
	public void showArticles(List<String> data) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void showLoading() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void hideLoading() {
		// TODO Auto-generated method stub
		
	}


}
此时,Presenter的创建以及与View建立关联等操作都被封装到MVPBaseActivity ,消除了子类重复代码的同时又避免了Activity的内存泄漏问题,你可以为Fragment、FragmentActivity等类型都建立一个类似这样的基类,这样一来你就可以将这种思想运用到更广阔的范围。

MVP是开发过程中非常值推荐的架构模式,它能够将各组件进行解耦,并且带来良好的可扩展性,可测试性,稳定性、可维护,同时使得每个类型的职责相对单一、简单,避免了大量的“臃肿”的程序,例如数千行的Activity类,它有效的将业务逻辑、数据处理等工作从Activity等View元素中抽离出来,使得每个类尽可能简单,同时每个模块能够独立进行演化。它的思想也非常好地体现了面向对象的设计原则,即抽象、单一职责、最小化、低耦合。






发布了49 篇原创文章 · 获赞 18 · 访问量 9万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章