Android App的架構(gòu)設(shè)計:從VM延蟹、MVC评矩、MVP到MVVM

隨著Android應(yīng)用開發(fā)規(guī)模的擴大,客戶端業(yè)務(wù)邏輯也越來越復(fù)雜阱飘,已然不是簡單的數(shù)據(jù)展示了斥杜。如同后端開發(fā)遇到瓶頸時采用的組件拆分思想虱颗,客戶端也需要進行架構(gòu)設(shè)計,拆分視圖和數(shù)據(jù)蔗喂,解除模塊之間的耦合忘渔,提高模塊內(nèi)部的聚合度。

開始之前先上一張內(nèi)部分享時用的PPT圖:


客戶端開發(fā)過程中面臨的問題

以上是筆者在客戶端開發(fā)過程中面臨的問題缰儿,涉及到以下四個主題:

  1. Android App的架構(gòu)設(shè)計:從VM畦粮、MVC、MVP到MVVM
  2. Android App的網(wǎng)絡(luò)訪問:支持REST乖阵、HTTPS及SPDY的Retrofit+Okhttp
  3. Android App的響應(yīng)式編程:RxJava/RxAndroid解決方案
  4. Android App的依賴注入:Dagger2和ButterKnife使用

本文將從架構(gòu)設(shè)計入手宣赔,分享筆者在Android開發(fā)中采用MVC、MVP及MVVM的一些想法瞪浸。

一儒将、Android原生開發(fā)中的MVC

Android原生開發(fā)采用XML文件實現(xiàn)頁面布局,通過Java在Activity中開發(fā)業(yè)務(wù)邏輯默终,這種開發(fā)模式實際上已經(jīng)采用了MVC的思想椅棺,分離視圖和控制器。MVC模式(Model–view–controller)是軟件工程中的一種軟件架構(gòu)模式齐蔽,把軟件系統(tǒng)分為三個基本部分:模型(Model)两疚、視圖(View)和控制器(Controller)。

MVC模式最早由Trygve Reenskaug在1978年提出含滴,是施樂帕羅奧多研究中心(Xerox
PARC)在20世紀80年代為程序語言Smalltalk發(fā)明的一種軟件架構(gòu)诱渤。MVC模式的目的是實現(xiàn)一種動態(tài)的程序設(shè)計,使后續(xù)對程序的修改和擴展簡化谈况,并且使程序某一部分的重復(fù)利用成為可能勺美。除此之外,此模式通過對復(fù)雜度的簡化碑韵,使程序結(jié)構(gòu)更加直觀赡茸。軟件系統(tǒng)通過對自身基本部分分離的同時也賦予了各個基本部分應(yīng)有的功能。專業(yè)人員可以通過自身的專長分組:

  • 控制器(Controller)- 負責(zé)轉(zhuǎn)發(fā)請求祝闻,對請求進行處理占卧。
  • 視圖(View) - 界面設(shè)計人員進行圖形界面設(shè)計。
  • 模型(Model) - 程序員編寫程序應(yīng)有的功能(實現(xiàn)算法等等)联喘、數(shù)據(jù)庫專家進行數(shù)據(jù)管理和數(shù)據(jù)庫設(shè)計(可以實現(xiàn)具體的功能)华蜒。
    ——以上內(nèi)容來自《維基百科》

在Android編程中,View對應(yīng)xml布局文件豁遭,Model對應(yīng)實體模型(網(wǎng)絡(luò)叭喜、數(shù)據(jù)庫、I/O)蓖谢,Controller對應(yīng)Activity業(yè)務(wù)邏輯捂蕴,數(shù)據(jù)處理和UI處理譬涡。如下圖所示。

MVC架構(gòu)

但在實際開發(fā)過程中启绰,純粹作為View的各個XML文件功能較弱昂儒,Activity基本上都是View和Controller的合體,既要負責(zé)視圖的顯示又要加入控制邏輯委可,承擔(dān)的功能很多,導(dǎo)致代碼量很大腊嗡。所有更貼切的目前常規(guī)的開發(fā)說應(yīng)該是View-Model模式着倾,大部分都是通過Activity的協(xié)調(diào),連接處理邏輯的燕少。

二卡者、從MVC過渡到MVP

在業(yè)務(wù)邏輯稍微復(fù)雜一點的頁面,Activity的代碼超過一千是很容易的客们,如果作者又剛好讀過《如何寫出無法維護的代碼》崇决,那么恭喜后來接手該代碼的童鞋,接下來的幾個月會很酸爽的底挫。恒傻。。

既然Activity存在代碼量過大的問題建邓,那自然會想到進行拆分盈厘。上節(jié)說到Android原生開發(fā)采用了MVC的思想,但Activity并不是一個標(biāo)準(zhǔn)的MVC模式中的Controller官边,它的首要職責(zé)是加載應(yīng)用的布局和初始化用戶界面沸手,并接受并處理來自用戶的操作請求,進而作出響應(yīng)注簿。隨著界面及其邏輯的復(fù)雜度不斷提升契吉,Activity類的職責(zé)不斷增加,以致變得龐大臃腫诡渴。

MVP是從MVC過渡而來捐晶,MVP框架由三部分組成:View負責(zé)顯示,Presenter負責(zé)邏輯處理玩徊,Model提供數(shù)據(jù)租悄。Android開發(fā)從MVC過渡到MVP,最主要的變化就是將Activity中負責(zé)業(yè)務(wù)邏輯的代碼移到Presenter中恩袱,Activity只充當(dāng)MVP中的View泣棋,負責(zé)界面初始化以及建立界面控件與Presenter的關(guān)聯(lián)。

這樣拆分之后畔塔,Presenter承擔(dān)了大量的邏輯操作潭辈,避免了Activity的臃腫鸯屿。整個架構(gòu)如下圖所示。

MVP架構(gòu)
  • View(Activity)負責(zé)響應(yīng)用戶操作把敢,通過Presenter暴露的方法請求數(shù)據(jù)寄摆;
  • Presenter在獲取數(shù)據(jù)后,通過View(Activity)暴露的方法實現(xiàn)界面控制(showLoading/showUsers)修赞;
  • Presenter的數(shù)據(jù)是通過Model來獲取的婶恼,Model包含網(wǎng)絡(luò)、數(shù)據(jù)庫以及I/O等柏副;
  • Model通過回調(diào)的方式將數(shù)據(jù)傳到Presenter中勾邦。

采用MVP明顯的優(yōu)點是避免了傳統(tǒng)開發(fā)模式中View和Model耦合的情況,提高了代碼可擴展性割择、組件復(fù)用能力眷篇、團隊協(xié)作的效率以及單元測試的便利性。但也有一些缺點荔泳,比如:

  • Model到Presenter的數(shù)據(jù)傳遞過程需要通過回調(diào)蕉饼;
  • View(Activity)需要持有Presenter的引用,同時玛歌,Presenter也需要持有View(Activity)的引用昧港,增加了控制的復(fù)雜度;
  • MVC中Activity的代碼很臃腫沾鳄,轉(zhuǎn)移到MVP的Presenter中慨飘,同樣造成了Presenter在業(yè)務(wù)邏輯復(fù)雜時的代碼臃腫。

三译荞、從Presenter到ViewModel

MVVM是Model-View-ViewModel的簡稱瓤的,從實際效果來看,ViewModel是View的數(shù)據(jù)模型和Presenter的結(jié)合吞歼,具體結(jié)構(gòu)如下圖所示:

MVVM架構(gòu)
  • View(視圖層)采用XML文件進行界面的描述圈膏;
  • Model(模型層)通過網(wǎng)絡(luò)和本地數(shù)據(jù)庫獲取視圖層所需數(shù)據(jù);
  • ViewModel(視圖-模型層)負責(zé)View和Model之間的通信篙骡,以此分離視圖和數(shù)據(jù)稽坤。

View和Model之間通過Android Data Binding技術(shù),實現(xiàn)視圖和數(shù)據(jù)的雙向綁定糯俗;ViewModel持有Model的引用尿褪,通過Model的方法請求數(shù)據(jù);獲取數(shù)據(jù)后得湘,通過Callback(回調(diào))的方式回到ViewModel中杖玲,由于ViewModel與View的雙向綁定,使得界面得以實時更新淘正。同時摆马,界面輸入的數(shù)據(jù)變化時臼闻,由于雙向綁定技術(shù),ViewModel中的數(shù)據(jù)得以實時更新囤采,提高了數(shù)據(jù)采集的效率述呐。

采用ViewModel解決MVP中View(Activity)和Presenter相互持有對方應(yīng)用的問題,界面由數(shù)據(jù)進行驅(qū)動蕉毯,響應(yīng)界面操作無需由View(Activity)傳遞乓搬,數(shù)據(jù)的變化也無需Presenter調(diào)用View(Activity)實現(xiàn),使得數(shù)據(jù)傳遞的過程更加簡潔恕刘,高效缤谎。

在Android中實現(xiàn)MVVM架構(gòu)的核心支撐技術(shù)是Google去年I/O大會開源的Data binding技術(shù),這項技術(shù)的思想并不新穎褐着,最初由微軟提出,在前端開發(fā)中已經(jīng)有成熟的應(yīng)用托呕。下面對其進行簡要的介紹含蓉。

四、Android中的Data Binding

學(xué)習(xí)Data Binding主要推薦兩個內(nèi)容:

官方的Data Binding教程
精通 Android Data Binding

這兩篇文章中已經(jīng)將Data Binding的基本內(nèi)容描述的很詳細了项郊。這里僅列兩個在實踐中遇到的坑馅扣,拋磚引玉。

  • ObservableField的get方法可能無法返回界面實時更新的內(nèi)容
public ObservableField<String> username = new ObservableField<>();

上述username表示用戶名着降,在界面上可能會與EditText綁定差油。通過username的set方法可以設(shè)置EditText顯示,但如果輸入變更后任洞,通過get方法卻不一定能及時返回界面的數(shù)據(jù)蓄喇。

  • Data Binding依然有很多支持的不好的組件(listview,recyclerView等)交掏,不可能通過給所有組件綁定ViewModel從而實現(xiàn)Activity沒有業(yè)務(wù)邏輯操作妆偏。另外,ViewModel獲取數(shù)據(jù)之后盅弛,也不可能把所有數(shù)據(jù)直接綁定到界面钱骂,有些也需要通過回調(diào)傳到Activity中。

從MVC挪鹏、MVP到MVVM见秽,實際上是模型和視圖的分離過程。MVC中模型和視圖沒有完全分離讨盒,造成Activity代碼臃腫解取,MVP中通過Presenter來進行中轉(zhuǎn),模型和視圖徹底分離催植,但由于V和P互相引用肮蛹,代碼不夠優(yōu)雅勺择。ViewModel通過Data Binding實現(xiàn)了視圖和數(shù)據(jù)的綁定,解決了這種MVP的缺陷伦忠,但目前也存在Data Binding還不成熟的問題省核。

其實,MVC昆码、MVP及MVVM沒有絕對好壞气忠,在軟件編程過程中,也沒必要非此即彼赋咽,最重要的是讓軟件高內(nèi)聚旧噪、低耦合、可維護脓匿、可擴展淘钟,至于架構(gòu),根據(jù)實際情況選擇吧陪毡。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末米母,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子毡琉,更是在濱河造成了極大的恐慌铁瞒,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件桅滋,死亡現(xiàn)場離奇詭異慧耍,居然都是意外死亡,警方通過查閱死者的電腦和手機丐谋,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進店門芍碧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事⊙。” “怎么了?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵践美,是天一觀的道長。 經(jīng)常有香客問我找岖,道長陨倡,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任许布,我火速辦了婚禮兴革,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己杂曲,他們只是感情好庶艾,可當(dāng)我...
    茶點故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著擎勘,像睡著了一般咱揍。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上棚饵,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天煤裙,我揣著相機與錄音,去河邊找鬼噪漾。 笑死硼砰,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的欣硼。 我是一名探鬼主播题翰,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼诈胜!你這毒婦竟也來了遍愿?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤耘斩,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后桅咆,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體括授,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年岩饼,在試婚紗的時候發(fā)現(xiàn)自己被綠了荚虚。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡籍茧,死狀恐怖版述,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情寞冯,我是刑警寧澤渴析,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站吮龄,受9級特大地震影響俭茧,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜漓帚,卻給世界環(huán)境...
    茶點故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一母债、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦毡们、人聲如沸迅皇。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽登颓。三九已至,卻和暖如春青责,著一層夾襖步出監(jiān)牢的瞬間挺据,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工脖隶, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留扁耐,地道東北人。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓产阱,卻偏偏與公主長得像婉称,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子构蹬,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,033評論 2 355

推薦閱讀更多精彩內(nèi)容