如何將既有項目重構成 MVP 模式

開源鉅獻:Google最熱門60款開源項目!很多幹貨!

吊炸天!74款APP完整源碼!

谷歌官方Android應用架構庫——LiveData

JavaAndroid架構

歡迎關注我們,一起討論技術,掃描和長按下方的二維碼可快速關注我們。搜索微信公衆號:JANiubility。

公衆號:JANiubility

最近在做公司項目的重構工作,主要重構點包括:

  • 網絡請求框架由 HttpURLConnection + Handler 改爲 Retrofit + OkHttp + RxJava

  • 事件通知由 安卓廣播 改爲 RxBus

  • 圖片加載框架由 ImageLoader 改爲 Glide

  • 代碼優化(瘦身,內存泄漏分析等)

  • 將傳統 Activity 作爲 God Object 的 MVC 模式 改爲兼容原代碼的MVP模式

這是現在Android應用的主流架構:

Retrofit + OkHttp + RxJava + MVP

今天主要分享一下,如何將原項目轉爲MVP模式,並且兼容原有代碼。有空的話再分享其他模塊的重構經過。

MVP,全稱 Model-View-Presenter,其中Presenter解耦了Model與View,使得每個模塊的職責更加單一,Model負責獲取數據,View只關心視圖的繪製,Presenter關聯Model和View處理業務邏輯。

與傳統的MVC模式相比更加易於維護和排查漏洞,以及更容易編寫單元測試。

MVP模式也有一些缺點,比如類文件數目增加,每一層都需要接口與實現類,在系統相對不是特別複雜的情況下可以捨棄Model層與Presenter接口,MVP模式並沒用固定的模板,其中每一層的實現可以根據各自的業務場景做相應的調整。

並不是所有的頁面都需要使用MVP模式,相對簡單的頁面完全可以用原來的實現模式。

推薦幾篇關於MVP模式介紹比較全面的文章:

Android MVP 詳解(上)
http://www.jianshu.com/p/9a6845b26856

Android MVP 詳解(下)
http://www.jianshu.com/p/0590f530c617

Google 官方Android MVP架構實踐
http://blog.csdn.net/u011459799/article/details/51360882


下面正式開始,如有不妥之處,請老司機多多指教。

首先定義各層的接口,各層之間通過接口耦合:

  1. View接口

public interface IView{ }

2.Model接口:

public interface IModel { }

3.Presenter 接口:

public interface IPresenter<T extends IView> {

   void attachView(T view);
   void start();
   void detachView();  
}

實現一下Ipresenter接口中簡單的邏輯:BasePresenter ,使用時直接繼承該類:

public abstract class BasePresenter<T extends IView,M extends IModel> implements IPresenter<T> {

   protected static final String TAG = "BasePresenter";
   protected T mView;
   protected M mModel;

   @Override
   public void attachView(T view) {
       mView = view;
   }

   @Override
   public void detachView() {
       mView = null;
   }

   public boolean isViewAttached() {
       return mView != null;
   }

   public T getView() {
       return mView;
   }

   public M getModel() {
      return mModel;
   }

}

到目前爲止MVP模式的基礎代碼已經編寫完成了,下面的介紹是爲了兼容原代碼。

現有項目中一般都會有一個BaseActivity,爲了方便在Activity中使用MVP模式,以及不影響現有頁面,再次實現一個IViewActivity繼承BaseActivity封裝MVP相關邏輯。如果要使用MVP模式則繼承IViewActivity,否則繼承BaseActivity,從而兼容了原有代碼,並且引入MVP模式開發新頁面。

下面是IViewActivity:

/**
* Mvp base activity
* Created by qiulinmin on 16-9-22.
*/

public abstract class IViewActivity<P extends IPresenter> extends BaseActi implements IView {

   protected P mPresenter;

   @Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       mPresenter = onLoadPresenter();
       getPresenter().attachView(this);
       initEventAndData();
       if(getPresenter() != null) {
           getPresenter().start();
       }
   }

   public P getPresenter() {
       return mPresenter;
   }

   @Override
   protected void onDestroy() {
       if (getPresenter() != null) {
           getPresenter().detachView();
       }
       super.onDestroy();
   }

   protected abstract P onLoadPresenter();
   protected abstract void initViews(Bundle savedInstanceState);
   protected abstract void initEventAndData();
}

在 onLoadPresenter() 中初始化Presenter,初始化工作完成之後會調用IPresenter.start()方法轉到Present層處理業務邏輯。

以上關於MVP模式所有代碼都已經編寫好了。

使用時爲了減少類文件數目,可以寫一個Contract接口來統一管理每一層的接口,例如:

public interface DemoContract {

   interface View extends IView {

   }

   interface Model extends IModel {

   }

   interface Presenter extends IPresenter<View> {

   }

}

最後實現present,model接口,

public class DemoPresenter extends BasePresenter<DemoContract.View, DemoContract.Model> implements DemoContract.presenter { }
public class DemoModel implements DemoContract.Model {  }

在DemoPresenter的構造器中需要初始化DemoModel,因爲是接口耦合的,在初始化DemoModel時完全可以替換成其他的實現。

最後的最後Activity作爲View層實現DemoContract.View:

public class DemoActivity extends IViewActivity<DemoContract.Presenter> implements DemoContract.View {

   protected DemoContract.Presenter onLoadPresenter() {
       return new DemoPresenter();
   }

   protected void initViews(Bundle savedInstanceState) {
       //略...
   }

   protected void initEventAndData() {
       //略...
   }

}

Activity頓時感到如釋重負,它只要關心如何繪製UI,把邏輯處理的工作丟給了Presenter,同時存取數據的活交給了Model,Presenter 通過 Model 獲取數據,通知 View 繪製界面。而且他們之間又是通過接口耦合的,只要替換掉實現,就能方便的改變需求,Presenter實現中可以不包含任何Android相關的代碼,因爲是純Java代碼,所以可以方便的使用JUnit配合Mokito進行單元測試

源碼及Demo下載關注下方公衆號後領取

更多學習資料點擊下面二維碼關注公衆號後領取


Java和Android架構

歡迎關注我們,一起討論技術,掃描和長按下方的二維碼可快速關注我們。搜索微信公衆號:JANiubility。

公衆號:JANiubility



發佈了26 篇原創文章 · 獲贊 4 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章