Android 項目架構 使用MVP開發

來源:互聯網
上載者:User

標籤:

前言

在Android中使用 MVP 來開發已經出來很久了,剛好Google又出了一系列的architecture samples,在此就整理一下對於MVP的認知和實踐總結,這篇文章會隨著使用經驗的豐富而不斷更新。

1. 介紹MVC

在沒有使用MVP開發之前,我們一直使用的都是MVC模式,其實也不算的MVC,一般我們聽到的都是Android中的Activity既是View,又是Controller,即Activity既負責View的顯示,又負責處理商務邏輯,這是我們一般聽到的,但其實我們的Activity還負責了資料的儲存和讀取。

當商務邏輯簡單,僅僅只是擷取資料、展示資料時,我們的代碼是這樣:

但其實考慮資料的儲存、商務邏輯等等,我們是這樣:

所有東西都連在一起,太複雜以至於成了一個面了,這個面就是這個God Object:Activity。

想想看,我們是不是把所有東西都寫在這個上帝類中了:網路請求、解析Json、處理資料、展示資料、快取資料等等,全部都在Activity中,儘管有些東西已經封裝的很好,但依舊都和Activity扯在一起,基本上所有代碼都在Activity中,於是所謂的MVC,就叫做 massive view controller,超級大的ViewController。
這樣做儘管有好處,很容易看清楚商務邏輯,而且寫起來很方便、順手,不知不覺就這樣寫了。但是很明顯,隨著需求不斷加多,該類代碼就越寫越多,並且如果需求有改動的話,那改起來很費勁,而且這樣寫,不敢輕易重構,因為太複雜,動一點可能就會有bug。

那麼不想這麼做怎麼辦呢?於是就有了MVP。

2. 介紹MVP

典型的MVP就像這樣:


很明顯:

  1. MVP中Presenter和View是相互互動的。
  2. MVP拒絕View和Model直接互動,View和Model只能通過Presenter間接互動。這點是合理的,因為Android對UI的操作必須在 UIThread 上,而對Model的處理大多是非同步任務。通過轉接一層,可以很方便處理線程問題。
  3. Model和View是被動的,一切都由Presenter來主導

我們一般把 Activity/Fragment 當做View,那麼這時我們的Activity/Fragment中的代碼簡單多了,響應Presenter的指令對View進行操作,而這些操作是在IVIEW 介面中定義好的。這樣大部分代碼轉移到了Presenter中,而且一些業務代碼被封裝到了Model層去,這樣的代碼就會清晰很多,寫完一看,哇塞,太清晰了。而且很容易定位bug,畢竟代碼職責越清晰越不容易出錯。

那麼現在分開來介紹:

  • Model
    為UI層提供的資料,或者儲存UI層傳下來的資料。
    Model 是使用者介面需要顯示資料的抽象,也可以理解為從業務資料(結果)那裡到使用者介面的抽象。
    Model 應該封裝商務邏輯,不讓Presenter和View知道商務邏輯層
  • View
    View is a layer that displays data and reacts to user actions.
    View提供友好的互動、展示資料、響應使用者操作,並都轉寄給Presenter來做具體的處理
  • Presenter
    邏輯控制層,分發邏輯。處理著程式各種邏輯的分發,收到View層UI上的反饋命令、定時命令、系統命令等指令後分發處理邏輯交由業務層做具體的業務操作,然後將得到的 Model 給 View 顯示。

到這裡,關於MVP的基本概念講解完了,就是分三層寫代碼,此處建議使用MVP時分包時按照模組分包,模組比較多時,建一個module包,裝所有模組,每個模組再細分三層,這樣包很清晰、代碼也很清晰。

接下來看一些google的樣本。

3. Google samples中的MVP

Google samples中的MVP(google MVP樣本中這張圖真的很完美的闡述了一個簡單的app的架構):

Model層擷取資料時,使用DataRepository 分發管理,從Presenter處接收指令從RemoteDataSource 或者 LocalDataSource 中擷取資料,並回調給Presenter,Presenter再回調給View用於展示。

下面列出一些官方推薦 的點,這些都可以在代碼中找到:

  • Use Fragments as View. The separation between Activity and Fragment fits nicely with this implementation of MVP: the Activity is the overall controller that creates and connects views and presenters,which means the Activity is responsible for the creation of fragments and presenters.
    使用Fragment作為View,Activity作為全域的Controller把presenter和view綁定起來。

  • Create a contract interface defining the view and the presenter,which contains the View interface and the presenter interface. Contracts are interfaces used to define the connection between views and presenters. This is a amazing concept.
    建立 IContract 父類介面來管理同一個模組下的 IViewIPresenter介面,這樣很清楚的能看清楚兩者的邏輯。

  • In general, the business logic lives in the presenter and relies on the view to do the Android UI work.
    商務邏輯全部在Presenter層,依靠View層來觸發。

  • The view contains almost no logic: it converts the presenter’s commands to UI actions and listens to user actions, which are passed to the presenter.
    View幾乎沒有任何邏輯,響應Presenter層的指令,並接收使用者操作傳給Prenster。當然很少很輕量的邏輯應該在這一層中處理(判空處理等),這一點應該要自己衡量。View應該是被動的。

4. MVP是一個方法論

我們應該很容易看到在MVP中僅僅有一些基本原則,並沒有一個固定的方式去實現MVP,都針對自家的業務需求、邏輯去更好的更合適的使用MVP,只要View和Model分離,代碼清晰,易於調試,易於測試,都OK。

MVP的一些指導性原則來約束實現:

  • Model與View不能直接通訊,只能通過Presenter
  • Presenter類似於中間人的角色進行協調和調度
  • Model和View是介面,Presenter持有的是一個Model介面和一個View介面
  • Model和View都應該是被動的,一切都由Presenter來主導
  • Model應該把與商務邏輯層的互動封裝掉,換句話說Presenter和View不應該知道商務邏輯層
  • View的邏輯應該儘可能的簡單,不應該有狀態。當事件發生時,調用Presenter來處理,並且不傳參數,Presenter處理時再調用View的方法來擷取。

知道了MVP是一個方法論,下面說說MVP的另一個實現方式。

5. MVP的另一種實現方式

MVP另一個實現方式(變種)就是不像一般的把Activity/Fragment作為View,而是把他們作為Presenter來使用,單獨把View用一個類來管理。

使用該種方式可以大大減少類的個數,因為是依靠 泛型 來解耦的,所以可以不用提供介面,當然提供了也行,我在實現過程中刪除了介面,同時把點擊事件的響應結果當成邏輯,放在Presenter中,這樣就不用傳來傳去的。(之前使用Fragment作為View時,點擊ListItem 需要修改已讀狀態,傳入到Presenter中修改,Presenter修改完後又調用View.showDetailUI()方法又傳回到View中,使用變種後這塊就大大減輕工作量了)

使用這種方式個人認為有點怪異,一是使用泛型加大了理解難度,寫著寫著就不知道怎麼調用到這塊了;二是刪除介面後感覺複用性降低了,邏輯也不能複用、View也不能複用,當然可以不刪介面,但是不刪介面和原來的MVP有什麼區別呢。恩,不過這點可能隨著使用MVP越深入會越能理解,Activity到底是View還是控制器,可能隨著項目的偏重不同,會適合不同的情況吧。

那麼說完了MVP變種,下面總結一下個人使用MVP的心得。

6. MVP心得體會

使用MVP開發,頓時感覺清爽很多,雖然多了很多代碼,但是瑕不掩瑜,讓代碼清爽很多。真的很棒,看了重構後的代碼,感覺自己之前真是活在噩夢裡一樣,終於不用把所有代碼寫在Activity裡或是Fragment裡了。下面就具體說說使用中的心得體會。

首先是方法論上:

  • 首先分清除什麼是 分發商務邏輯、商務邏輯、視圖邏輯。
    理解這三點對於設計介面、使用MVP寫項目、重構等有很大的協助。視圖邏輯可以更好的寫View,分發商務邏輯用於Presenter,商務邏輯用於Model,當然一些商務邏輯是在Presenter中的。

  • 然後看什麼是View,什麼是邏輯,哪些邏輯展示哪些View,哪些操作調用哪些邏輯,這會很好的協助我們理清代碼邏輯、方便相互調用。

  • 一個 View 可以有多個 Presenter,要用到什麼業務就加入什麼 Presenter,並且實現這個 Presenter 所需要的 View 介面即可,這就是簡單的複用邏輯,即Presenter是可複用的。

然後是代碼上:

  • IView介面裡的方法全部是UI相關,show()、hide()等,不應該出現邏輯相關。
  • IPresenter介面裡的方法應該全部是邏輯相關,進行分發,很明顯,要持有Model引用,方便對資料進行操作。不應該出現與Model相關的方法,比如LoadFromLocal,LoadFromRemote,這應該是DataRepository處理的事情。Presenter裡面只需要告訴Model說我需要這個資料,即LoadData,而不用管從哪Load資料。這裡面只需要負責 分發!!!
  • Model中,對資料進行處理,所有的資料從這裡進出,並對資料進行處理。一般建立DataRepository類對LocalDataSource,RemoteDataSource進行管理分發,這三個類都實現IDataSource介面,保證邏輯一致。

最後一些個人體會:

  • 在MVP裡面,越來越感到依賴注入的重要性。全部是依賴,全部需要注入,感覺依賴注入架構 Dagger2 是時候展現它強大的功能了。

  • 回調太多。擷取資料時,從Presenter中開始callback,再到DataRepository中,再到具體的LocalDataSource或RemoteDataSource的callback,總共回調了三層,增長了鏈條。很明顯,解決這個問題需要用到 RxJava 了,可以省去很多代碼,變得簡潔是必然的。

  • Google samples 中的 IContract 介面管理類真的非常棒,管理了IPresenter和IView,如果可以的話,應該讓它也管理IDataSource 這個介面,非常清晰的一種方式。

  • 儘管MVP實現了一定的分離,但相當於大量代碼從Activity中轉移到Presenter和Model中,儘管使用介面使代碼清晰很多,但避免不了難看和難以尋找,隨著業務的不斷複雜,代碼依舊會越來越多。所以使用clean架構應該是最好。

  • 最後不得不說確實方法數、類都增加了好多。但這也是必然的。解耦、方便測試。

7. 代碼實現

說了那麼說,show me the code.

那麼,自己寫的代碼全在GitHub上,全部以分支形式展現:

  • 最基礎的分支,全部代碼在Activity中: branch_basic

  • MVP分支,使用MVP重構代碼:branch_mvp

  • MVP另一種實現方式(變種)分支:branch_mvp_variant

之後,肯定會嘗試clean架構再次重構。不過由於項目本身較小,所以當個練手的真的不錯。


參考:

  • 介紹MVP,非常好的文章
    Android MVP模式 簡單易懂的介紹方式
    Android中的MVP
    Introduction to Model View Presenter on Android

  • MVP變種:
    用MVP架構開發Android應用
    Android MVP?—?An Alternate Approach

  • MVP方法論,具有哲學意味的一篇文章,看完後會覺得原來代碼還能這麼哲學:
    說說Android的MVP模式

Android 項目架構 使用MVP開發

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.