Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android清晰架構設計

Android清晰架構設計

編輯:關於Android編程

大家都知道要寫一款精品軟件是有難度且很復雜的:不僅要滿足特定要求,而且軟件還必須具有穩健性,可維護、可測試性強,並且能夠靈活適應各種發展與變化。這時候,“清晰架構”就應運而生了,這一架構在開發任何軟件應用的時候用起來非常順手。

這個思路很簡單:簡潔架構 意味著產品系統中遵循一系列的習慣原則:

框架獨立性
可測試
UI獨立性
數據庫獨立性
任何外部代理模塊的獨立性

我們並不要求一定要用四環結構(如圖所示),這只是一個示例圖解,但是要考慮的是依賴項規則:源碼依賴項只能向內指向,內環裡的所有項不能了解外環所發生的東西。

以下是更好地理解和熟悉本方法的一些相關詞匯:

Entities:是指一款應用的業務對象
Use cases:是指結合數據流和實體中的用例,也稱為Interactor
Interface Adapters: 這一組適配器,是負責以最合理的格式轉換用例(use cases)和實體(entities)之間的數據,表現層(Presenters )和控制層(Controllers ),就屬於這一塊的。
Frameworks and Drivers: 這裡是所有具體的實現了:比如:UI,工具類,基礎框架,等等。

想要更具體,更生動豐富的解釋,可以參考這篇文章或者這個視頻。
場景

我會設置一個簡單的場景來開始:創建一個簡單的小app,app中顯示從雲端獲取的一個朋友或用戶列表。當點擊其中任何一個時,會打開一個新的窗口,顯示該用戶的詳細信息。這裡我放了一段視頻,大家看看這個視頻 (需翻牆)大概就可以對我所描述的東西了解個大概了。
Android應用架構

這一對象遵循關注分離原則,也就是通過業務規則讓內環操作對外環事物一無所知,這樣一來,在測試時它們就不會依賴任何的外部元素了。
要達到這個目的,我的建議就是把一個項目分成三個層次,每個層次擁有自己的目的並且各自獨立於堆放運作。
值得一提的是,每一層次使用其自有的數據模型以達到獨立性的目的(大家可以看到,在代碼中需要一個數據映射器來完成數據轉換。如果你不想把你的模型和整個應用交叉使用,這是你要付出的代價)。

以下是圖解,大家感受下:

注:我並沒有使用任何的外部庫(除了用於json數據句法分析的gson和用於測試的junit, mockito, robolectric和espresso以外)。原因是它可以使這個示例更清晰。總之,在存儲磁盤數據時,記得加上ORM、依賴注入框架或者你熟悉的任何工具或庫,這些都會帶來很大幫助。(記住:重復制造輪子可不是明智的選擇)

表現層 (Presentation Layer)

表現層在此,表現的是與視圖和動畫相關的邏輯。這裡僅用了一個Model View Presenter(下文簡稱MVP),但是大家也可以用MVC或MVVM等模式。這裡我不再贅述細節,但是需要強調的是,這裡的fragment和activity都是View,其內部除了UI邏輯以外沒有其他邏輯,這也是所有渲染的東西發生的地方。
本層次的Presenter由多個interactor(用例)組成,Presenter在 android UI 線程以外的新線程裡工作,並通過回調將要渲染到View上的數據傳遞回來。

如果你需要一個使用MVP和MVVM的Effective Android UI典型案例,可以參考我朋友Pedro Gómez的文章。
領域層 (Domain Layer)

這裡的業務規則是指所有在本層發生的邏輯。對於Android項目來說,大家還可以看到所有的interactor(用例)實施。這一層是純粹的java模塊,沒有任何的Android依賴性。當涉及到業務對象時,所有的外部組件都使用接口。

數據層 (Data Layer)

應用所需的所有數據都來自這一層中的UserRepository實現(接口在領域層)。這一實現采用了Repository Pattern,主要策略是通過一個工廠根據一定的條件選取不同的數據來源。
比如,通過ID獲取一個用戶時,如果這個用戶在緩存中已經存在,則硬盤緩存數據源會被選中,否則會通過向雲端發起請求獲取數據,然後存儲到硬盤緩存。
這一切背後的原理是由於原始數據對於客戶端是透明的,客戶端並不關心數據是來源於內存、硬盤還是雲端,它需要關心的是數據可以正確地獲取到。

注:在代碼方面,出於學習目的,我通過文件系統和Android preference實現了一個簡單、原始的硬盤緩存。請記住,如果已經存在了能夠完成這些工作的庫,就不要重復制造輪子。

錯誤處理

這是一個長期待解決的討論話題,如果大家能夠分享各自的解決方案,那真真是極好的。
我的策略是使用回調,這樣的話,如果數據倉庫發生了變化,回調有兩個方法:onResponse()和onError(). onError方法將異常信息封裝到一個ErrorBundle對象中: 這種方法的難點在於這其中會存在一環扣一環的回調鏈,錯誤會沿著這條回調鏈到達展示層。因此會犧牲一點代碼的可讀性。另外,如果出現錯誤,我本來可以通過事件總線系統拋出事件,但是這種實現方式類似於使用C語言的goto語法。在我看來,當你訂閱多個事件時,如果不能很好的控制,你可能會被弄得暈頭轉向。
測試

關於測試方面,我根據不同的層來選擇不同的方法:

展示層 ( Presentation Layer) : 使用android instrumentation和 espresso進行集成和功能測試
領域層 ( Domain Layer) : 使用JUnit和Mockito進行單元測試;
數據層 ( Data Layer) : 使用Robolectric ( 因為依賴於Android SDK中的類 )進行集成測試和單元測試。

代碼展示

我猜你現在在想,扯了那麼久的淡,代碼究竟在哪裡呢? 好吧,這就是你可以找到上述解決方案的github鏈接。還要提一點,在文件夾結構方面,不同的層是通過以下不同的模塊反應的:

presentation: 展示層的Android模塊
domain: 一個沒有android依賴的java模塊
data: 一個數據獲取來源的android模塊。
data-test: 數據層測試,由於使用Robolectric 存在一些限制,所以我得再獨立的java模塊中使用。

結論

正如 Bob大叔 所說:“Architecture is About Intent, not Frameworks” ,我非常同意這個說法,當然了,有很多不同的方法做不同的事情(不同的實現方法),我很確定,你每天(像我一樣)會面臨很多挑戰,但是遵循這些方法,可以確保你的應用會:

易維護
易測試
高內聚
低耦合

最後,我強烈推薦你去實踐一下,並且分享你的經驗。也許你會找到更好的解決方案:我們都知道,不斷提升自己是一件件非常好的事。我希望這篇文章對你有所幫助,歡迎拍磚。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved