自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Android開發(fā)中的MVP架構(gòu)

移動(dòng)開發(fā) Android
最近越來越多的人開始談?wù)摷軜?gòu)。我周圍的同事和工程師也是如此。盡管我還不是特別深入理解MVP和DDD,但是我們的新項(xiàng)目還是決定通過MVP來構(gòu)建。這篇文章是我通過研究和學(xué)習(xí)各種文章以及專題討論所總結(jié)出來的。

最近越來越多的人開始談?wù)摷軜?gòu)。我周圍的同事和工程師也是如此。盡管我還不是特別深入理解MVP和DDD,但是我們的新項(xiàng)目還是決定通過MVP來構(gòu)建。

這篇文章是我通過研究和學(xué)習(xí)各種文章以及專題討論所總結(jié)出來的,它包括以下幾點(diǎn):

  • 為什么越來越多的人開始關(guān)注架構(gòu)?
  • 首先,MVP是什么?
  • 哪種架構(gòu)才是***的,MVC,MVVM還是MVP?
  • MVP的利與弊
  • Show me the code!!!代碼展示

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

  • 詳細(xì)生動(dòng)的代碼示例
  • 如何編寫測試代碼

***,我將告訴你如何更進(jìn)一步學(xué)習(xí)這些專題。

順便提一下,我于上周在當(dāng)?shù)氐囊粋€(gè)研討會(huì)上對(duì)MVP架構(gòu)進(jìn)行了相關(guān)演講。這篇文章與當(dāng)時(shí)的演講內(nèi)容相差無幾。

介紹~Activity是上帝類~

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

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

避免創(chuàng)建神類。避免創(chuàng)建無所不知,無所不能的上帝類。如果一個(gè)類需要花費(fèi)時(shí)間從其他類中通過Get()和Set()檢索數(shù)據(jù)(也就是說,需要深入業(yè)務(wù)并且告訴它們?nèi)绾稳プ?,所以是否應(yīng)該把這些功能函數(shù)更好的組織到其它類而不是上帝類中。(Riel 1996)

上帝類的維護(hù)成本很高,你很難理解正在進(jìn)行的操作,并且難以測試和擴(kuò)展,這就是為什么要避免創(chuàng)建上帝類的黃金法則。

然而,在Android開發(fā)中,如果你不考慮架構(gòu)的話,Activity類往往會(huì)越來越大。這是因?yàn)椋贏ndroid中,允許View和其它線程共存于Activity內(nèi)。其實(shí)***的問題莫過于在Activity中同時(shí)存在業(yè)務(wù)邏輯和UI邏輯。這會(huì)增加測試和維護(hù)的成本。 

 

 

 

Activity是上帝

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

什么是MVP?

MVP代表Model,View和Presenter。

  • View層負(fù)責(zé)處理用戶事件和視圖部分的展示。在Android中,它可能是Activity或者Fragment類。
  • Model層負(fù)責(zé)訪問數(shù)據(jù)。數(shù)據(jù)可以是遠(yuǎn)端的Server API,本地?cái)?shù)據(jù)庫或者SharedPreference等。
  • Presenter層是連接(或適配)View和Model的橋梁。

下圖是基于MVP架構(gòu)的模式之一。View是UI線程。Presenter是View與Model之間的適配器。UseCase或者Domain在Model層中,負(fù)責(zé)從實(shí)體獲取或載入數(shù)據(jù)。依賴規(guī)則如下: 

 

 

 

The Dependency Injection

關(guān)鍵是,高層接口不知道底層接口的細(xì)節(jié),或者更準(zhǔn)確地說,高層接口不能,不應(yīng)該,并且必須不了解底層接口的細(xì)節(jié),是(面向)抽象的,并且是細(xì)節(jié)隱藏的。 

 

 

 

The higher interfaces do not know about the details of the lower ones

依賴規(guī)則?

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

同心圓將軟件劃分為不同的區(qū)域,一般的,隨著層級(jí)的深入,軟件的等級(jí)也就越高。外圓是實(shí)現(xiàn)機(jī)制,內(nèi)圓是核心策略。

這是上面片文章的摘要:

Enitities:

  • 可以是一個(gè)持有方法函數(shù)的對(duì)象
  • 可以是一組數(shù)據(jù)結(jié)構(gòu)或方法函數(shù)
  • 它并不重要,能在項(xiàng)目中被不同應(yīng)用程序使用即可

Use Cases

  • 包含特定于應(yīng)用程序的業(yè)務(wù)規(guī)則
  • 精心編排流入Entity或從Entity流出的數(shù)據(jù)
  • 指揮Entity直接使用項(xiàng)目范圍內(nèi)的業(yè)務(wù)規(guī)則,從而實(shí)現(xiàn)Use Case的目標(biāo)

Presenters Controllers

  • 將Use Case和Entity中的數(shù)據(jù)轉(zhuǎn)換成格式最方便的數(shù)據(jù)
  • 外部系統(tǒng),如數(shù)據(jù)庫或網(wǎng)頁能夠方便的使用這些數(shù)據(jù)
  • 完全包含GUI的MVC架構(gòu)

External Interfaces, UI, DB

  • 所有的細(xì)節(jié)所在
  • 如數(shù)據(jù)庫細(xì)節(jié),Web框架細(xì)節(jié),等等

MVC,MVP還是MVVM?

那么,哪一個(gè)才是***的呢?哪一個(gè)比其他的更優(yōu)秀呢?我能只選擇一個(gè)嗎?

答案是,NO。

這些模式的動(dòng)機(jī)都是一樣的。那就是如何避免復(fù)雜混亂的代碼,讓執(zhí)行單元測試變得容易,創(chuàng)造高質(zhì)量應(yīng)用程序。就這樣。

當(dāng)然,遠(yuǎn)不止這三種架構(gòu)模式。而且任何一種模式都不可能是銀彈,他們只是架構(gòu)模式之一,不是解決問題的唯一途徑。這些只是方法、手段而不是目的、目標(biāo)。

利與弊

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

**利

  • 可測試(TDD)
  • 可維護(hù)(代碼復(fù)用)
  • 容易R(shí)eviewe
  • 信息隱蔽

**弊

  • 冗余的,尤其是小型App開發(fā)
  • (有可能)額外的學(xué)習(xí)曲線
  • 開始編寫代碼之前需要時(shí)間成本(但是我敢打賭,設(shè)計(jì)架構(gòu)是所有項(xiàng)目開發(fā)所必需的)

show me the code!!!

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

首先,為每一個(gè)View定義接口。

  1. /** 
  2.  * Interface classes for the Top view 
  3.  */ 
  4. public interface TopView { 
  5.   
  6.     /** 
  7.      * Initialize the view
  8.      *  
  9.      * e.g. the facade-pattern method for handling all Actionbar settings 
  10.      */ 
  11.     void initViews(); 
  12.   
  13.     /** 
  14.      * Open {<a href="http://www.jobbole.com/members/57845349">@link</a> DatePickerDialog} 
  15.      */ 
  16.     void openDatePickerDialog(); 
  17.   
  18.     /** 
  19.      * Start ListActivity 
  20.      */ 
  21.     void startListActivity(); 
  22.  

讓我們重寫TopView類,要點(diǎn)如下:

  • TopActivity只是負(fù)責(zé)處理事件監(jiān)聽或者展示每個(gè)視圖組件
  • 所有的業(yè)務(wù)邏輯必須委托給Presenter類
  • 在MVP中,View和Presenter是一 一對(duì)應(yīng)的(在MVVM中是一對(duì)多的) 
  1. public class TopActivity extends Activity implements TopView { 
  2.   
  3.   // here we use ButterKnife to inject views 
  4.   /** 
  5.    * Calendar Title 
  6.    */ 
  7.   @Bind(R.id.calendar_title) 
  8.   TextView mCalendarTitle; 
  9.   
  10.   private TopPresenter mTopPresenter; 
  11.   
  12.   @Override 
  13.   protected void onCreate(Bundle savedInstanceState) { 
  14.       super.onCreate(savedInstanceState); 
  15.       setContentView(R.layout.activity_top); 
  16.       ButterKnife.bind(this); 
  17.   
  18.       // Save TopPresenter instance in a meber variable field 
  19.       mTopPresenter = new TopPresenter(); 
  20.       mTopPresenter.onCreate(this); 
  21.   } 
  22.   
  23.   /* 
  24.    * Overrides method from the {<a href="http://www.jobbole.com/members/57845349">@link</a> TopView} interfaces 
  25.    */ 
  26.   
  27.   @Override 
  28.   public void initViews() { 
  29.       // Actionbar settins 
  30.   
  31.       // set event listeners 
  32.   } 
  33.   
  34.   @Override 
  35.   public void openDatePickerDialog() { 
  36.       DatePickerFragment.newInstance().show(getSupportFragmentManager(), 
  37.               DatePickerFragment.TAG); 
  38.   
  39.       // do not write logic here... all logic must be passed to the Presenter 
  40.       mTopPresenter.updateCalendarDate(); 
  41.   } 
  42.   
  43.   @Override 
  44.   public void startListActivity() { 
  45.       startActivity(new Intent(this, ListActivity.class)); 
  46.   } 
  47.  

這是Presenter類,最重要的一點(diǎn)是Presenter僅僅是連接View與Model的適配橋梁。比如,TopUseCase#saveCalendarDate()是對(duì)TopPresenter細(xì)節(jié)隱藏的,同樣對(duì)TopView也是如此。你不需要關(guān)心數(shù)據(jù)結(jié)構(gòu),也不需要關(guān)心業(yè)務(wù)邏輯是如何工作的。因此你可以對(duì)TopUseCase執(zhí)行單元測試,因?yàn)闃I(yè)務(wù)邏輯與視圖層是分離的。 

  1. public class TopPresenter { 
  2.   
  3.     @Nullable 
  4.     private TopView mView; 
  5.   
  6.     private TopUseCase mUseCase; 
  7.   
  8.     public TopPresenter() { 
  9.       mUseCase = new TopUseCase(); 
  10.     } 
  11.   
  12.     public void onCreate(@NonNull TopView topView) { 
  13.         mView = topView; 
  14.   
  15.         // here you call View's implemented methods 
  16.         mView.initViews(); 
  17.     } 
  18.   
  19.     public void updateCalendarDate() { 
  20.         // do not forget to return if view instances is null 
  21.         if (mView == null) { 
  22.             return
  23.         } 
  24.   
  25.         // here logic comes 
  26.         String dateToDisplay = mUseCase.getDateToDisplay(mContext.getResources()); 
  27.         mView.updateCalendarDate(dateToDisplay); 
  28.   
  29.         // here you save dateand this logic is hidden in UseCase class 
  30.         mUseCase.saveCalendarDate(); 
  31.     } 
  32.  

當(dāng)然,盡管業(yè)務(wù)邏輯被實(shí)現(xiàn)在Activity類中,你依然可以執(zhí)行單元測試,只不過這會(huì)耗費(fèi)很多時(shí)間,而且有些復(fù)雜??赡苄枰嗟臅r(shí)間來運(yùn)行App,相反,你本應(yīng)該充分利用測試類庫的性能,如Robolectric。

總結(jié)

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

責(zé)任編輯:龐桂玉 來源: 安卓開發(fā)精選
相關(guān)推薦

2017-02-17 10:07:02

AndroidMVP模式實(shí)例

2017-11-29 09:34:03

MVP蘇寧移動(dòng)

2018-10-29 11:41:22

架構(gòu)MVCAndroid

2018-12-13 10:37:13

Android開發(fā)框架

2011-05-31 08:54:37

Android開發(fā) 架構(gòu)

2011-03-29 13:03:59

IronRubyWindows Pho.NET

2018-06-08 14:06:02

MVP架構(gòu)Android

2009-07-06 10:36:41

敏捷開發(fā)

2024-03-01 08:23:39

2023-02-06 15:24:50

軟件開發(fā)MVP功能

2009-04-30 15:56:50

三層架構(gòu)MVCMVP

2023-04-11 07:50:27

軟件架構(gòu)設(shè)計(jì)

2011-01-13 14:29:54

2013-01-08 13:46:58

Android開發(fā)ViewStub布局

2023-11-06 13:17:53

ServiceAndroid

2011-05-26 15:22:57

Android Activity

2013-06-25 11:06:07

Android開發(fā)顏色定義方法

2014-06-18 14:41:26

AndroidHandler總結(jié)

2009-05-30 09:29:52

AndroidGoogle移動(dòng)OS

2013-04-03 11:07:34

Android開發(fā)良好習(xí)慣有用習(xí)慣
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)