App的架構之旅

1. 架構設計的目的
對程序進行架構設計的原因,歸根到底是為了提高生產力。通過設計使程序模塊化,做到模塊內部的高聚合和模塊之間的低耦合。這樣做的好處是使得程序在開發的過程中,開發人員只需要專注于一點,提高程序開發的效率,并且更容易進行后續的測試以及定位問題。但設計不能違背目的,對于不同量級的工程,具體架構的實現方式必然是不同的,切忌犯為了設計而設計,為了架構而架構的毛病。舉個簡單的例子,一個Android App如果只有3個Java文件,那只需要做點模塊和層次的劃分就可以,引入框架或者架構反而提高了工作量,降低了生產力。但我當前開發的App最終代碼量應該在10W行以上,本地需要進行復雜操作,同時也需要考慮到與其余的Android開發者以及后臺開發人員之間的同步配合,那就需要在架構上進行一些思考。
2. 基于MVP的架構設計思路
在App開發過程中,經常出現的問題就是某一部分的代碼量過大,雖然做了模塊劃分和接口隔離,但也很難完全避免。從實踐中看到,這更多的出現在UI部分,也就是Activity里。我曾見過2000+行以上基本不帶注釋的Activity,那時我的第一反應就是想吐。Activity內容過多的原因其實很好解釋,因為Activity本身需要擔負與用戶之間的操作交互,再加上現在大部分的Activity還對整個App起到控制器的作用,這又帶入了大量的邏輯代碼,造成Activity的臃腫。為了解決這個問題,我們引入了MVP框架思路。
2.1 什么是MVP?
MVP是一種使用廣泛的基礎架構模式,使用基于事件驅動的應用框架。MVP從更早的MVC框架演變過來的一種框架,與MVC有一定的相似性。MVP框架由3部分組成:View負責顯示,Presenter負責邏輯處理,Model提供數據。MVP與MVC之間最主要的區別在控制層上,在MVP框架中,View與Model并不直接交互,所有的交互放在Presenter中;而在MVC里,View與Model會直接產生一定的交互。MVP的Presenter是框架的控制者,承擔了大量的邏輯操作,而MVC的Controller更多時候承擔一種轉發的作用。因此在App中引入MVP的原因,是為了將此前在Activty中包含的大量邏輯操作放到控制層中,避免Activity的臃腫。MVP的變種有很多,其中使用最廣泛的是Passive View模式,即被動視圖。在這種模式下,整個框架內部模塊之間的邏輯操作均由Presenter控制,View僅僅是整個操作的匯報者和結果接收者,Model根據Presenter的單向調用返回數據(圖片來自網絡)。并且MVP模式使得View與Model的耦合性更低,降低了Presenter對View的依賴,實現了關注點分離的初衷,方便開發人員的編碼和測試工作。

MVC VS MVP

具體到Android App中,我一般將App根據程序的結構進行縱向劃分,對應MVP分別為模型層,UI層和邏輯層。UI層一般包括Activity,Fragment,Adapter等直接和UI相關的類,UI層的Activity在啟動之后實例化相應的Presenter,App的控制權后移,由UI轉移到Presenter,兩者之間的通信通過BroadCast、Handler或者接口完成,只傳遞事件和結果。舉個簡單的例子,UI層通知邏輯層(Presenter)用戶點擊了一個Button,邏輯層(Presenter)自己決定應該用什么行為進行響應,該找哪個模型(Model)去做這件事,最后邏輯層(Presenter)將完成的結果更新到UI層。
2.2 MVP架構存在的問題
轉移邏輯操作之后可能部分較為復雜的Activity內代碼量還是不少,于是在分層的基礎上再加入模板方法(Template Method)。具體做法是在Activity內部分層。其中最頂層為BaseActivity,不做具體顯示,而是提供一些基礎樣式,Dialog,ActionBar在內的內容,展現給用戶的Activity繼承BaseActivity,重寫BaseActivity預留的方法。如有必要再進行二次繼承,App中Activity之間的繼承次數最多不超過3次。
模型層(Model)中的整體代碼量是最大的,一般由大量的Package組成,針對這部分需要做的就是在程序設計的過程中,做好模塊的劃分,進行接口隔離,在內部進行分層。
強化Presenter的作用,將所有邏輯操作都放在Presenter內也容易造成Presenter內的代碼量過大,對于這點,我的方法是在UI層和Presenter之間設置中介者Mediator,將例如數據校驗、組裝在內的輕量級邏輯操作放在Mediator中;在Presenter和Model之間使用代理Proxy;通過上述兩者分擔一部分Presenter的邏輯操作,但整體框架的控制權還是在Presenter手中。Mediator和Proxy不是必須的,只在Presenter負擔過大時才建議使用。最終的架構如下圖所示:

改進后的MVP

3 基于AOP的框架設計
AOP(Aspect-Oriented Programming, 面向切面編程),誕生于上個世紀90年代,是對OOP(Object-Oriented Programming, 面向對象編程)的補充和完善。OOP引入封裝、繼承和多態性等概念來建立一種對象層次結構,用以模擬公共行為的一個集合。當我們需要為分散的對象引入公共行為的時候,OOP則顯得無能為力。也就是說,OOP允許你定義從上到下的關系,但并不適合定義從左到右的關系。例如日志功能。日志代碼往往水平地散布在所有對象層次中,而與它所散布到的對象的核心功能毫無關系。對于其他類型的代碼,如安全性、異常處理和透明的持續性也是如此。這種散布在各處的無關的代碼被稱為橫切(Cross-Cutting)代碼,在OOP設計中,它導致了大量代碼的重復,而不利于各個模塊的重用。而AOP技術則恰恰相反,它利用一種稱為“橫切”的技術,剖解開封裝的對象內部,并將那些影響了多個類的公共行為封裝到一個可重用模塊,并將其名為“Aspect”,即方面。所謂“方面”,簡單地說,就是將那些與業務無關,卻為業務模塊所共同調用的邏輯或責任封裝起來,便于減少系統的重復代碼,降低模塊間的耦合度,并有利于未來的可操作性和可維護性。
3.1.類庫的使用
BufferKnife 注解
https://github.com/JakeWharton/butterknife
OrmLite Sqlite操作
https://github.com/j256/ormlite-android
Android-Universal-Image-Loader 圖片緩存
https://github.com/nostra13/Android-Universal-Image-Loader
4 快速開發框架
目前網絡上也有一些針對Android的快速開發框架,下面介紹3個主要的快速開發框架。針對這些快速開發框架,個人認為可以參考,但并不推薦使用,因為App整N體依賴一個個人維護的框架風險實在太大,框架存在一些學習成本,本身也不一定完全符合App的需求,使用后的收益并沒有想象中大。
4.1 Afinal
Afinal是一個Android的IOC,ORM框架,內置了四大模塊功能:FinalAcitivity, FinalBitmap, FinalDb, FinalHttp。通過FinalActivity,可以通過注解的方式進行綁定UI和事件。通過FinalBitmap,可以方便的加載Bitmap圖片,而無需考慮OOM等問題。通過FinalDB模塊,通過一行代碼就可以對Android的SQlite數據庫進行增刪改查。通過FinalHttp模塊,可以以Ajax形式請求Http數據。
GitHub項目地址:Afinal
4.2 xUtils
xUtils目前主要包括4大模塊:DbUtils, ViewUtils, HttpUtils, BitmapUtils。包含了很多實用的Android工具;支持大文件上傳,更全面的Http請求協議支持,擁有更加靈活的ORM,更多的事件注解支持且不受混淆影響;最低兼容Android 2.2 (Api Level 8)。
GitHub項目地址:xUtils
4.3 ThinkAndroid
** **ThinkAndroid是一個免費的開源的、簡易的、遵循Apache2開源協議發布的Android開發框架,其開發宗旨是簡單、快速的進行 Android應用程序的開發,包含Android MVC、簡易SQlite ORM、IOC模塊、封裝Android HttpClitent的Http模塊, 具有快速構建文件緩存功能,無需考慮緩存文件的格式,都可以非常輕松的實現緩存,它還基于文件緩存模塊實現了圖片緩存功能, 在Android中加載的圖片的時候,對OOM的問題,和對加載圖片錯位的問題都輕易解決。他還包括了一個手機開發中經常應用的實用工具類, 如日志管理,配置文件管理,Android下載器模塊,網絡切換檢測等等工具。
GitHub項目地址:ThinkAndroid

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,786評論 6 534
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,656評論 3 419
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 176,697評論 0 379
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,098評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,855評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,254評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,322評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,473評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,014評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,833評論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,016評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,568評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,273評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,680評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,946評論 1 288
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,730評論 3 393
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,006評論 2 374

推薦閱讀更多精彩內容