Android中的MVP

RobynTooth 11年前發布 | 19K 次閱讀 Android開發 移動開發 MVP Android

前言

MVP作為一種MVC的演化版本在Android開發中受到了越來越多的關注,但在項目開發中選擇一種這樣的軟件設計模式需保持慎重心態,一旦確定使用MVP作為你App的開發模式那么你就最好堅持做下去,如果在使用MVP模式開發過程中發現問題而且坑越來越大,這時你想用MVC等來重新設計的話基本上就等于推倒重來了。要知道在Android上MVP在現在為止并沒有統一的標準或者框架,不像SSH這三個成熟穩重強而有力的三劍客支持推動著Java EE的開發,所以在運用MVP時一定要做好自己的理解,并且盡量預知自己App各模塊的需求(客戶說改改改,我們就改改改 :-( )以便提前做好充分的設計工作。當然MVP既然能出現那么必然有它的優點的,不然誰會理會這個冒出來的東西,下面就對Android中MVP做一些闡述。

MVP簡介

相信大家對MVC都是比較熟悉了:M-Model-模型V-View-視圖C-Controller-控制器,MVP作為MVC的演化版本,也是作為用戶界面(用戶層)的實現模式,那么類似的MVP所對應的意義:M-Model-模型V-View-視圖P-Presenter-表示器。從MVC和MVP兩者結合來看,Controlller/Presenter在MVC/MVP中都起著邏輯控制處理的角色,起著控制各業務流程的作用。而MVP與MVC最不同的一點是M與V是不直接關聯的也是就Model與View不存在直接關系,這兩者之間間隔著的是Presenter層,其負責調控View與Model之間的間接交互,MVP的結構圖如下所示,對于這個圖理解即可而不必限于其中的條條框框,畢竟在不同的場景下多少會有些出入的。在Android中很重要的一點就是對UI的操作基本上需要異步進行也就是在MainThread中才能操作UI,所以對View與Model的切斷分離是合理的。此外Presenter與View、Model的交互使用接口定義交互操作可以進一步達到松耦合也可以通過接口更加方便地進行單元測試。
Android中的MVPMVP結構圖

MVP之Model

Model 是用戶界面需要顯示數據的抽象,也可以理解為從業務數據(結果)那里到用戶界面的抽象(Business rule, data access, model classes)。本文 Demo 為了簡單處理就直接把業務放到了對應的 Model 之中。

MVP之View

視圖這一層體現的很輕薄,負責顯示數據、提供友好界面跟用戶交互就行。MVP下Activity和Fragment體現在了這一層,Activity一般也就做加載UI視圖、設置監聽再交由Presenter處理的一些工作,所以也就需要持有相應Presenter的引用。例如,Activity上滾動列表時隱藏或者顯示Acionbar(Toolbar),這樣的UI邏輯時也應該在這一層。另外在View上輸入的數據做一些判斷時,例如,EditText的輸入數據,假如是簡單的非空判斷則可以作為View層的邏輯,而當需要對EditText的數據進行更復雜的比較時,如從數據庫獲取本地數據進行判斷時明顯需要經過Model層才能返回了,所以這些細節需要自己掂量。

MVP之Presenter

Presenter這一層處理著程序各種邏輯的分發,收到View層UI上的反饋命令、定時命令、系統命令等指令后分發處理邏輯交由業務層做具體的業務操作,然后將得到的 Model 給 View 顯示。

演示demo

動手寫起代碼來才有更好的感覺。demo很簡單,還是上個圖更直觀,輸入城市的代號,點擊按鈕獲取城市的天氣信息然后顯示出來,網絡操作使用Volley框架,解析用Gson,其它的就手寫了。整個項目的包設計如下:
Android中的MVP包結構
Android中的MVP項目效果預覽
包圖中明顯的三層:Model包、Presenter包、UI包,其中,三者都實現各自的結構,Model為WeatherModel、Presenter為WeatherPresenter、View為Weather,那么具體實現類就是impl包里的了,View層的即為Activity。此外的app和util包無關緊要可以不看。可以看到采用MVP設計后項目明顯多了很多東西,這也是不可避免的,使用原始方法可以使項目開起來簡單些但是以后還有維護呢、測試呢、加功能呢、。。。
entity里的實體屬性基本上對應json里的這些屬性了,代碼不貼了,View里面的接口:

1
2
3
4
5
6
public interface WeatherView {
    void showLoading();
    void hideLoading();
    void showError();
    void setWeatherInfo(Weather weather);
}

 

WeatherPresenter的接口:

  • 1
    2
    3
    4
    5
    6
    
    public interface WeatherPresenter {
        /**

     * 獲取天氣的邏輯
     */
    void getWeather(String cityNO);
    

    } </code></pre> </td> </tr> </tbody> </table>

     

    WeatherModel接口:

    1
    2
    3
    
    public interface WeatherModel {
        void loadWeather(String cityNO, OnWeatherListener listener);
    }
    

     

    prestener里面還有個OnWeatherListener,其在Presenter層實現,給Model層回調,更改View層的狀態,確保Model層不直接操作View層。如果沒有這一接口在WeatherPresenterImpl實現的話,WeatherPresenterImpl只有View和Model的引用那么Model怎么把結果告訴View呢?當然這只是一種解決方案,在實際項目中可以使用Dagger、EventBus、Otto等第三方框架結合進來達到更加松耦合的設計。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    
    public interface OnWeatherListener {
        /**

     * 成功時回調
     *
     * @param weather
     */
    void onSuccess(Weather weather);
    /**
     * 失敗時回調,簡單處理,沒做什么
     */
    void onError();
    

    } </code></pre> </td> </tr> </tbody> </table>

     

    所以demo的代碼流程:Activity做了一些UI初始化的東西并需要實例化對應WeatherPresenter的引用和實現WeatherView的接口,監聽界面動作,Go按鈕按下后即接收到查詢天氣的事件,在onClick里接收到即通過WeatherPresenter的引用把它交給WeatherPresenter處理。WeatherPresenter接收到了查詢天氣的邏輯就知道要查詢天氣了,然后把查詢天氣的具體業務實現交給WeatherModel去實現同時把WeatherListener即WeatherPresenter自己傳給WeatherModel。WeatherModel進行查詢天氣業務后即把結果通過WeatherListener回調通知WeatherPresenter,WeatherPresenter再把結果返回給View層的Activity,最后Activity顯示結果。就這樣,拍磚之處請拍。

    End

    采用哪種軟件設計模式都是為了達到如下目的,找到合適的加以運用就是最好的:

    • 易于維護
    • 易于測試
    • 松耦合度
    • 復用性高
    • 健壯穩定

    本文demo
    Rocko’s MVP demo
    MVP相關demo
    androidmvp
    ActivityFragmentMVP
    EffectiveAndroidUI
    MvpCleanArchitecture
    Material-Movies

    相關參考文章
    50個Android開發技巧(20 使用MVP模式)
    MVP for Android: how to organize the presentation layer(英文原版)
    MVP for Android: how to organize the presentation layer(中文譯文)
    從三層架構到MVC,MVP
    Architecting Android…The clean way?(中文譯文)
    TED MOSBY - SOFTWARE ARCHITECT

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