【譯】Android開發中的MVP架構

jopen 8年前發布 | 20K 次閱讀 Android開發 移動開發

最近越來越多的人開始談論架構。我周圍的同事和工程師也是如此。盡管我還不是特別深入理解MVP和DDD,但是我們的新項目還是決定通過MVP來構建。

這篇文章是我通過研究和學習各種文章以及專題討論所總結出來的,它包括以下幾點:

  • 為什么越來越多的人開始關注架構?

  • 首先,MVP是什么?

  • 哪種架構才是最好的,MVC,MVVM還是MVP?

  • MVP的利與弊

  • Show me the code!!!代碼展示

不幸的,這篇文章將不包括:

  • 詳細生動的代碼示例

  • 如何編寫測試代碼

最后,我將告訴你如何更進一步學習這些專題。

順便提一下,我于上周在當地的一個研討會上對MVP架構進行了相關演講。這篇文章與當時的演講內容相差無幾。

(譯者注:閱讀更多請點擊原作者PPT

介紹~Activity是上帝類~

首先,讓我們思考一下為什么在Android開發中如此迫切地需要一個清晰的軟件架構。

該段摘自“代碼大全第二版”:

避免創建神類。避免創建無所不知,無所不能的上帝類。如果一個類需要花費時間從其他類中通過Get()和Set()檢索數據(也就是說,需要深入業務并且告訴它們如何去做),所以是否應該把這些功能函數更好的組織到其它類而不是上帝類中。(Riel 1996)

上帝類的維護成本很高,你很難理解正在進行的操作,并且難以測試和擴展,這就是為什么要避免創建上帝類的黃金法則。

然而,在Android開發中,如果你不考慮架構的話,Activity類往往會越來越大。這是因為,在Android中,允許View和其它線程共存于Activity內。其實最大的問題莫過于在Activity中同時存在業務邏輯和UI邏輯。這會增加測試和維護的成本。


Activity是上帝
</div>

這是為什么需要清晰架構的原因之一。不僅會造成Activity的臃腫,還會引起其他問題,如使Activity和Fragment的生命周期變復雜,以及數據綁定等。

什么是MVP?

MVP代表Model,View和Presenter。

  • View層負責處理用戶事件和視圖部分的展示。在Android中,它可能是Activity或者Fragment類。

  • Model層負責訪問數據。數據可以是遠端的Server API,本地數據庫或者SharedPreference等。

  • Presenter層是連接(或適配)View和Model的橋梁。

下圖是基于MVP架構的模式之一。View是UI線程。Presenter是View與Model之間的適配器。UseCase或者Domain在Model層中,負責從實體獲取或載入數據。依賴規則如下:


The Dependency Injection
</div>

關鍵是,高層接口不知道底層接口的細節,或者更準確地說,高層接口不能,不應該,并且必須不了解底層接口的細節,是(面向)抽象的,并且是細節隱藏的


The higher interfaces do not know about the details of the lower ones
</div>

依賴規則?

Uncle Bob的“The Clean Architecture”描述了依賴的規則是什么。

同心圓將軟件劃分為不同的區域,一般的,隨著層級的深入,軟件的等級也就越高。外圓是實現機制,內圓是核心策略。

這是上面片文章的摘要:

Entities:

  • 可以是一個持有方法函數的對象

  • 可以是一組數據結構或方法函數

  • 它并不重要,能在項目中被不同應用程序使用即可

Use Cases

  • 包含特定于應用程序的業務規則

  • 精心編排流入Entity或從Entity流出的數據

  • 指揮Entity直接使用項目范圍內的業務規則,從而實現Use Case的目標

Presenters,,Controllers

  • 將Use Case和Entity中的數據轉換成格式最方便的數據

  • 外部系統,如數據庫或網頁能夠方便的使用這些數據

  • 完全包含GUI的MVC架構

External Interfaces, UI, DB

  • 所有的細節所在

  • 如數據庫細節,Web框架細節,等等

MVC,MVP還是MVVM?

那么,哪一個才是最好的呢?哪一個比其他的更優秀呢?我能只選擇一個嗎?

答案是,NO。

這些模式的動機都是一樣的。那就是如何避免復雜混亂的代碼,讓執行單元測試變得容易,創造高質量應用程序。就這樣。

當然,遠不止這三種架構模式。而且任何一種模式都不可能是銀彈,他們只是架構模式之一,不是解決問題的唯一途徑。這些只是方法、手段而不是目的、目標。

利與弊

OK,讓我們回到MVP架構上。剛剛我們了解了什么是MVP,討論了MVP以及其它熱門架構,并且介紹了MVC,MVP和MVVM三者間的不同。這是關于MVP架構利與弊的總結:

**利

  • 可測試(TDD)

  • 可維護(代碼復用)

  • 容易Reviewe

  • 信息隱蔽

**弊

  • 冗余的,尤其是小型App開發

  • (有可能)額外的學習曲線

  • 開始編寫代碼之前需要時間成本(但是我敢打賭,設計架構是所有項目開發所必需的)

Show me the code!!!

這里僅展示了MVP模式的一小段結構。如果你想了解更多項目或生動的代碼示例,請參考文章末尾的“鏈接和資源”。那里有非常豐富和設計巧妙的示例,基本都托管在Github上,以便你能clone,在設備上運行,并了解工作原理。

首先,為每一個View定義接口。

/**

  • Interface classes for the Top view */ public interface TopView {

    /**

    • Initialize the view.
    • e.g. the facade-pattern method for handling all Actionbar settings */ void initViews();

      /**

    • Open {@link DatePickerDialog} */ void openDatePickerDialog();

      /**

    • Start ListActivity */ void startListActivity(); }</pre>

      讓我們重寫TopView類,要點如下:

      • TopActivity只是負責處理事件監聽或者展示每個視圖組件

      • 所有的業務邏輯必須委托給Presenter類

      • 在MVP中,View和Presenter是一 一對應的(在MVVM中是一對多的)

        public class TopActivity extends Activity implements TopView {

      // here we use ButterKnife to inject views /**

      • Calendar Title */ @Bind(R.id.calendar_title) TextView mCalendarTitle;

      private TopPresenter mTopPresenter;

      @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_top); ButterKnife.bind(this);

      // Save TopPresenter instance in a meber variable field mTopPresenter = new TopPresenter(); mTopPresenter.onCreate(this); }

      /*

      • Overrides method from the {@link TopView} interfaces */

      @Override public void initViews() { // Actionbar settins

      // set event listeners }

      @Override public void openDatePickerDialog() { DatePickerFragment.newInstance().show(getSupportFragmentManager(),

             DatePickerFragment.TAG);
      
      

      // do not write logic here... all logic must be passed to the Presenter mTopPresenter.updateCalendarDate(); }

      @Override public void startListActivity() { startActivity(new Intent(this, ListActivity.class)); } }</pre></li> </ul>

      這是Presenter類,最重要的一點是Presenter僅僅是連接View與Model的適配橋梁。比如,TopUseCase#saveCalendarDate()是對TopPresenter細節隱藏的,同樣對TopView也是如此。你不需要關心數據結構,也不需要關心業務邏輯是如何工作的。因此你可以對TopUseCase執行單元測試,因為業務邏輯與視圖層是分離的。

      ublic class TopPresenter {
      
       @Nullable
       private TopView mView;
      
       private TopUseCase mUseCase;
      
       public TopPresenter() {
         mUseCase = new TopUseCase();
       }
      
       public void onCreate(@NonNull TopView topView) {
           mView = topView;
      
           // here you call View's implemented methods
           mView.initViews();
       }
      
       public void updateCalendarDate() {
           // do not forget to return if view instances is null
           if (mView == null) {
               return;
           }
      
           // here logic comes
           String dateToDisplay = mUseCase.getDateToDisplay(mContext.getResources());
           mView.updateCalendarDate(dateToDisplay);
      
           // here you save date, and this logic is hidden in UseCase class
           mUseCase.saveCalendarDate();
       }
      }

      當然,盡管業務邏輯被實現在Activity類中,你依然可以執行單元測試,只不過這會耗費很多時間,而且有些復雜。可能需要更多的時間來運行App,相反,你本應該充分利用測試類庫的性能,如Robolectric

      總結

      這里沒有萬能藥,而且MVP也僅僅是解決方案之一,它可以與其他方法協同使用,同樣,也可以有選擇的用于不同項目。

      鏈接和資源

      The Clean Architecture(譯者注:清晰架構。譯文) - Uncle Bob

      這篇文章由Uncle Bob撰寫,描述了依賴規則的樣子和它們之間的組件是如何工作的。我從一開始談論的那張圖表的靈感就來源于他的文章,雖然這篇文章不是針對Android開發的,但是同往常一樣,字里行間蘊藏著很多精辟的道理,所以,必讀。

      Architecting Android…The clean way? (譯者注:Android中的清晰架構。譯文)- Fernando Cejas

      我認為這是在探索如何將MVP架構到Android開發專題中最著名,也是最受歡迎的博客。我也是從他那篇簡單易讀,書寫良好的博客中偶然發現“MVP”這個名詞的。他的示例代碼托管在Github上,以便那些想要將MVP架構運用到正式App上的Android開發者clone到。

      Android Architecture(譯者注:Android架構) - Thanos Karpouzis

      一個在Android項目中運用MVC,MVP,MVVM的簡單指導。我從他的那篇普通卻不平凡的文章中學到了很多,尤其是MVC,MVP和MVVM之間的不同。

      Software Design patterns on Android English(譯者注:Android開發中的軟件設計模式) - Pedro Vicente Gómez Sánchez

      這是一個在Karumi工作的高級Android開發工程師所講的,他解釋了一些MVP架構中的設計模式(如,渲染模式,倉庫模式和命令模式)。如果你想深入理解MVC或者MVP,那這就使你要找的。

      M — Model in MVC, MVP, MVVC in Android(譯者注:MVC,MVP,MVVC架構中Model層在Android中的定義) - Artem Zinnatullin

      如果你不還了解Model層中的JSON與SQL,或者不能透徹理解Model層的圖像模型,這篇文章將帶你進一步理解什么是Model層以及為什么Model層獨立于其他層。其中“Model layer is solution”部分很好的解釋了如何通過面向接口的方式編寫測試。

      來自: http://www.jianshu.com/p/7567ed0d1853

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!