在完成了一些專案之後,我根據個人經驗,總結了一下如何正確地設計一個Android應用架構。
首先要分享的就是Bob大叔的一篇文章
好的架構有如下特點:
- 獨立於UI
- 獨立於任何框架
- 獨立於任何第三方服務
- 獨立於資料庫
- 易於測試
為什麼要把精力花在架構上
在開始這篇文章之前,我要講一講架構的重要性以及為什麼要花費時間和資源去搭建一個好的架構。有的開發團隊不設計架構直接開工,這樣做看似省去不少麻煩,但一般結果都不佳,所以開發前一定要先設計好架構。
使用MVP
近些年,有許多Android架構在開發社群中頗受青睞,比如MVP或MVVM,討論它們的人越來越多。
為什麼要使用MVP?
在Android開發中層有一個大問題,就是Activity和介面與資料獲取類耦合太緊,導致View層的任務太重,幾乎無法維護或擴充套件。理想情況下MVP要將不同View中的邏輯分離出來。MVP將View從資料中分離出來,並將整個應用分為至少三層,而這三層又能分別測試。
- Model層包含要展示在View(UI)中的資料。
- View層包含負責展示資料並將使用者事件傳遞給Presenter的介面。
- Presenter是Model與View的中間人,它持有二者的引用。
使用ReactiveX: RxJava/RxAndroid
當一個安卓應用中有很多的網路操作、使用者互動與動畫程式碼時,專案中可能會有大量的回撥方法,也就出現了回撥地獄(Callback Hell)。ReactiveX提供了另一種處理非同步任務和事件的解決方案。
RxJava是一個響應式擴充套件(Reactive Extensions)的JVM實現。由NetFlix開發,當下正火。
RxJava現在正是Android開發社群的焦點。雖然上手可能會有些困難,但一旦真正使用上RxJava,你就會喜歡上RxJava,因為它能非常cool地避免回撥地獄。
使用依賴注入框架: Dagger2
在Clean架構中,程式碼被分層成洋蔥狀,並遵循一個基本原則:內層不知道有關外層的任何東西。也就是說依賴是由外向內的。Dagger2有如下特點:
- 因為依賴可以在外部被注入與配置,所以元件可以重用。
- 依賴的注入和配置獨立於元件之外,注入的物件在一個獨立、不耦合的地方初始化,這樣在改變注入物件時,我們只需要修改物件的實現方法,而不用大改程式碼庫。
- 依賴可以注入到一個元件中:我們可以注入這些依賴的模擬實現,這樣使得測試更加簡單。
使用Dagger2會帶來至少以下幾點優勢:
- 簡化對共享例項的訪問,就像ButterKnife一樣。
- 即使對於複雜的依賴,配置也很簡單。
- 簡化單元測試。
- 給例項設定區間,讓你輕鬆管理不同生命週期(甚至是Application生命週期)的例項。
使用Lambda表達: Retrolambda
Retrolambda是用來在Android與非jdk8平臺上使用Lambda表示式的Java庫。它讓你的程式碼更緊湊且可讀性更強,尤其適合配合RxJava等函式式程式碼使用。
正確地打包JAVA程式碼: 依據功能而不是層
在編寫一個應用時會問的一個問題就是把程式碼分在哪幾個包裡?對於傳統的應用,一般有兩種打包方式:
依據功能打包
在這種打包方式中,包名對應著任務,或說功能。每個包中一般只包括負責對應功能的類,比如如下結構:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
abderrazak.com.recycleviewcardview ├─ data │ ├─ local │ ├─ model │ └─ remote ├─ injection │ ├─ component │ └─ module ├─ ui │ ├─ main │ ├─ detail │ └─ etc.. ├─ util └─ views ├─ adapters └─ widgets |
這種打包方式的優勢:
- 可以一下看出APP是幹什麼的。
- 程式碼模組化程度高。
- 更方便找檔案。
- 抽象成都更高。
- 將不同功能與不同層有效分開。
- 結構易讀且易維護。
- 檔案間粘合度高。
- 易於量化
- 不容易錯誤修改類或檔案。
- 易於新增或移除應用功能。
- 模組易於複用。
依據層打包
在這種打包方式中,最上層的包對應著應用的不同層,而不是功能,比如如下結構:
1 2 3 4 5 6 7 8 |
abderrazak.com.recycleviewcardview ├ ├─ model ├─ activities ├─ services ├─ fragments ├─ util └─ etc.. |
在這種專案結構中,每個功能的實現被分散在不同的目錄中。每個目錄中的檔案之間沒有什麼關係,這就導致專案包粘合度低並且模組化差,且不同包之間耦合度高。結果就是,當修改功能時,會在不同的包中修改各種檔案,尤其幾乎無法刪除某個功能。
專案構建:使用Gradle
開發Android,就用Gradle,這本來就是安卓開發用的官方構建工具,下面羅列一下使用這個自動化構建工具的一部分好處:
- 構建App的不同風格版本。
- 下載並管理依賴庫。
- 自定義keystore。
- 適應Android專案結構。
測試:Espresso/JUnit/Mockito/Robolectric
在開發的過程中就應該有測試的環節。測試可以讓你確認程式是否正確、功能是否執行、整個應用是否可用等。
- Presentation層:使用Espresso2和Instrumentation來測試UI。
- Domain層:因為是純Java層,所以使用JUnit和Mockito進行測試。
- Data層:使用Robolectric3、JUnit和Mockito測試。曾經這個層的測試程式碼需要單寫一個模組,因為那時IDE沒有內建單元測試,所以搭建一個類似於Robolectric的框架並不容易。
總結
幸運的是,應用架構是當下焦點,有太多的文章和部落格在探討不同的Android應用架構,從老牌的MVC/MVP/MVVM到一些新奇的方式比如Square使用的Mortar和Flow。
希望這篇文章可以幫助你更好的架構未來的Android應用。