[框架模式]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萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章