天天看點

應用架構原則

前言

基礎架構好壞直接決定所開發項目未來的穩定性、可伸縮性。在jetpack 架構出來之前應用架構大部分是從網絡上東拼西湊出來的産物,沒有考慮日後維護.對于google官方提供的應用架構原則,應該認真研讀。

移動應用使用者體驗

典型的 Android 應用包含多個應用元件,包括 ​​Activity​​​、​​Fragment​​​、​​Service​​​、​​内容提供程式​​​和​​廣播接收器​​。您需要在應用清單中聲明其中的大多數應用元件。Android 作業系統随後會使用此檔案來決定如何将您的應用內建到裝置的整體使用者體驗中。鑒于典型的 Android 應用可能包含多個元件,并且使用者經常會在短時間内與多個應用進行互動,是以應用需要适應不同類型的使用者驅動型工作流和任務。

請注意,移動裝置的資源也很有限,是以作業系統可能随時終止某些應用程序以便為新的程序騰出空間。

鑒于這種環境條件,您的應用元件可以不按順序地單獨啟動,并且作業系統或使用者可以随時銷毀它們。由于這些事件不受您的控制,是以您不應在記憶體中存儲或保留任何應用資料或狀态,并且應用元件不應互相依賴。

常見的架構原則

如果您不應使用應用元件存儲應用資料和狀态,那麼您應該改為如何設計應用呢?

随着 Android 應用大小不斷增加,您定義的架構務必要能允許應用擴縮、提升應用的穩健性并且友善對應用進行測試。

應用架構定義了應用的各個部分之間的界限以及每個部分應承擔的職責。為了滿足上述需求,您應該按照某些特定原則設計應用架構。

分離關注點

避免将業務邏輯一股腦的寫入Activity和Fragment, activity 和 Fragment 隻是系統與應用的粘合劑。系統會在記憶體緊張,或者臨界狀态删除fragment 或者 Activity

資料模型驅動界面。

另一個重要原則是您應該通過資料模型驅動界面 (最好是持久性模型),資料模型代表應用的資料。它們獨立于應用中的界面元素和其他元件。這意味着它們與界面和應用元件的生命周期沒有關聯,但仍會在作業系統決定從記憶體中移除應用的程序時被銷毀。

優點:

  1. 斷網或者網絡異常時,應用還可以繼續工作
  2. activity或者Framgent被銷毀後,不會導緻使用者資料丢失
  3. 應用會更便于測試、更穩定可靠

推薦的應用架構

最常見的三層應用架構 與MVC,MVVM ,MVI 各層定義的職責不同,看似細微的差别其實裡面蘊藏着新的架構思想在裡面。

應用架構原則

( 如圖:箭頭表示方向代表各層之間的依賴關系)

界面層(ui 元素,View Model)

界面層(或呈現層)的作用是在螢幕上顯示應用資料。無論是因為使用者互動(例如按下按鈕)還是外部輸入(例如網絡響應)導緻資料發生變化時,界面都應更新以反映相應的變化。

界面層由以下兩部分組成:

在螢幕上呈現資料的界面元素。您可以使用 View 或 Jetpack Compose 函數建構這些元素。

用于存儲資料、向界面提供資料以及處理邏輯的狀态容器(如 ViewModel 類)。

應用架構原則

如需詳細了解,​​請參閱界面層頁面​​

網域層

網域層是位于界面與資料層之間的可選層。

網域層負責封裝複雜的業務邏輯,或者由多個 ViewModel 重複使用的簡單業務邏輯。此層是可選的,因為并非所有應用都有這類需求。請僅在需要時使用該層,例如處理複雜邏輯或支援可重用性

應用架構原則

該層中的類通常稱為用例或互動方。每個用例都應僅負責單個功能。例如,如果多個 ViewModel 依賴時區在螢幕上顯示适當的消息,則您的應用可能具有 GetTimeZoneUseCase 類。

如需詳細了解此層,​​請參閱網域層頁面​​​。

資料層

應用的資料層包含業務邏輯。業務邏輯決定應用的價值,它包含決定應用如何建立、存儲和更改資料的規則。

資料層由多個代碼庫組成,其中每個代碼庫可包含零到多個資料源。您應該為應用處理的每種不同類型的資料建立一個代碼庫類。例如,您可以為與電影相關的資料建立 MoviesRepository 類,或者為與付款相關的資料建立 PaymentsRepository 類。

應用架構原則

代碼庫類負責以下任務:

  • 向應用的其餘部分提供資料。
  • 對資料進行集中更改。
  • 解決多個資料源之間的沖突。
  • 從應用的其餘部分中提取資料源。
  • 包含業務邏輯。

每個資料源類應僅負責處理一個資料源,該資料源可以是檔案、網絡來源或本地資料庫。資料源類是應用與資料作業系統之間的橋梁。

管理元件之間的依賴關系

應用中的類要依賴其他類才能正常工作。您可以使用以下任一設計模式來收集特定類的依賴項:

  • 依賴注入 (DI):依賴注入使類能夠定義其依賴項而不構造它們。在運作時,另一個類負責提供這些依賴項。
  • 服務定位器:服務定位器模式提供了一個系統資料庫,類可以從中擷取其依賴項而不構造它們。

您可以借助這些模式來擴充代碼,因為它們可提供清晰的依賴項管理模式(無需複制代碼,也不會增添複雜性)。 此外,您還可以借助這些模式在測試和生産實作之間快速切換。

我們建議在 Android 應用中采用依賴項注入模式并使用 Hilt 庫。Hilt 通過周遊依賴項樹自動構造對象,為依賴項提供編譯時保證,并為 Android 架構類建立依賴項容器

常見的最佳做法

程式設計是一個創造性的領域,建構 Android 應用也不例外。 無論是在多個 Activity 或 Fragment 之間傳遞資料,檢索遠端資料并将其保留在本地以在離線模式下使用,還是複雜應用遇到的任何其他常見情況,解決問題的方法都會有很多種。

雖然以下建議不是強制性的,但在大多數情況下,遵循這些建議會使您的代碼庫更強大、可測試性更高且更易維護:

不要将資料存儲在應用元件中。

請避免将應用的入口點(如 Activity、Service 和廣播接收器)指定為資料源。相反,您應隻将其與其他元件協調,以檢索與該入口點相關的資料子集。每個應用元件存在的時間都很短暫,具體取決于使用者與其裝置的互動情況以及系統目前的整體運作狀況。

減少對 Android 類的依賴。

您的應用元件應該是唯一依賴于 Android 架構 SDK API (例如 Context 或 Toast)的類。将應用中的其他類與這些類分離開來有助于改善可測試性,并減少應用中的耦合。

在應用的各個子產品之間設定明确定義的職責界限。

例如,請勿在代碼庫中将從網絡加載資料的代碼散布到多個類或軟體包中。同樣,也不要将不相關的職責(如資料緩存和資料綁定)定義到同一個類中。遵循推薦的應用架構可以幫助您解決此問題。

盡量少公開每個子產品中的代碼。

例如,請勿試圖建立從子產品提供内部實作細節的快捷方式。短期内,您可能會省點時間,但随着代碼庫的不斷發展,您可能會反複陷入技術上的麻煩。

專注于應用的獨特核心,以使其從其他應用中脫穎而出。

不要一次又一次地編寫相同的樣闆代碼,這是在做無用功。 相反,您應将時間和精力集中放在能讓應用與衆不同的方面上,并讓 Jetpack 庫以及建議的其他庫處理重複的樣闆。

考慮如何使應用的每個部分可獨立測試。

例如,如果使用明确定義的 API 從網絡擷取資料,将會更容易測試在本地資料庫中保留該資料的子產品。如果您将這兩個子產品的邏輯混放在一處,或将網絡代碼分散在整個代碼庫中,那麼即便能夠進行有效測試,難度也會大很多。

保留盡可能多的相關資料和最新資料。

這樣,即使使用者的裝置處于離線模式,他們也可以使用您應用的功能。請記住,并非所有使用者都能享受到穩定的高速連接配接 - 即使有時可以使用,在比較擁擠的地方網絡信号也可能不佳