Android 專案重構之路:架構篇

發表於2015-11-19

Android專案重構之路:架構篇
Android專案重構之路:介面篇
Android專案重構之路:實現篇


去年10月底換到了新公司,做移動研發組的負責人,剛開始接手android專案時,發現該專案真的是一團糟。

首先是其架構,是按功能模組進行劃分的,本來按模組劃分也挺好的,可是他卻分得太細,總共分為了17個模組,而好幾個模組也就只有兩三個類而已。但應用本身其實比較簡單,要按功能模組來分的話,最多五個模組就夠了。

另外,有好多模組劃分也很模糊,也有很多類按其功能其實可以屬於多個模組的,也有些類定義不明確,做了不該做的事。有時候,我要找一個介面的Activity,按照其功能應該屬於A模組的,可是在A模組裡卻找不到,於是,我只好去AndroidManifest檔案裡找了,找到才發現原來在B模組裡。

也有時候,我要找另一個介面的Activity,可我看遍了所有模組,也沒看出這個介面應該屬於哪個模組,沒法子,又只能去AndroidManifest檔案裡找了,找到才發現竟然在C模組裡。程式碼也是又亂又臭,導致出現一大堆bug又不好找,改好一個bug又出現另一個。整個專案從架構到程式碼都是又臭又亂,開發人員只是不停地改bug,根本沒法做新功能,更別談擴充套件了。

當時,公司已經有為不同客戶定製化app的需求,而現有的架構完全無法滿足這樣的需求。因此,我決定重構,搭建一個易維護、易擴充套件、可定製的專案。

我將專案分為了四個層級:模型層、介面層、核心層、介面層。模型層定義了所有的模型;介面層封裝了伺服器提供的API;核心層處理所有業務邏輯;介面層就處理介面的展示。幾個層級之間的關係如下圖所示:

下面展開說明具體的每個層次:

介面層

介面層封裝了網路底層的API,並提供給核心層呼叫。剛開始,為了簡單,該層的核心類我只定義了4個:

  1. PostEngine,請求引擎類,對請求的傳送和響應結果進行處理;
  2. Response,響應類,封裝了Http請求返回的資料結構;
  3. Api,介面類,定義了所有介面方法;
  4. ApiImpl,介面實現類,實現所有介面方法。

PostEngine將請求封裝好傳送到伺服器,並對響應結果的json資料轉化為Response物件返回。Response其實就是響應結果的json資料實體類,json資料是有固定結構的,分為三類,如下:

event為返回碼,0表示成功,msg則是返回的資訊,obj是返回的單個資料物件,objList是返回的資料物件陣列,currentPage表示當前頁,pageSize則表示當前頁最多物件數量,maxCount表示物件資料總量,maxPage表示總共有多少頁。根據此結構,Response基本的定義如下:

每個屬性名稱都要與json資料對應的名稱相一致,否則無法轉化。obj和objList用泛型則可以轉化為相應的具體物件了。

Api介面類定義了所有的介面方法,方法定義類似如下:

ApiImpl則實現所有Api介面了,實現程式碼類似如下:

實現中將請求引數和返回的型別定義好,呼叫PostEngine物件進行處理。
介面層的核心基本上就是這些了。

核心層

核心層介於介面層和介面層之間,主要處理業務邏輯,集中做資料處理。向上,給介面層提供資料處理的介面,稱為Action;向下,呼叫介面層向伺服器請求資料。向上的Action中定義的方法類似如下:

這是一個獲取使用者資訊的方法,因為需要向介面層請求伺服器Api資料,所以新增了callback監聽器,在callback裡對返回的資料結果進行操作。CallbackListener就定義了一個成功和一個失敗的方法,程式碼如下:

介面的實現基本分為兩步:

  1. 引數檢查,檢查引數的合法性,包括非空檢查、邊界檢查、有效性檢查等;
  2. 使用非同步任務呼叫介面層的Api,返回響應結果。

需要注意的是,Action是面向介面的,介面上的資料可能需要根據不同情況呼叫不同的Api。
後續擴充套件可以在這裡新增快取,但也要視不同情況而定,比如有些變化太快的資料,新增快取就不太適合了。

介面層

介面層處於最上層,其核心就是負責介面的展示。

因為公司有為不同商戶定製不同app的需求,因此,這裡就需要建立多個app的介面,這是一個很麻煩的事情,還好,Android Studio提供了很方便的方法可以大大減少工作量,主要通過設定Gradle,不同app可以新增不同的productFlavors。

介面層package的定義我也並不按照舊版的功能模組劃分,而根據不同型別劃分,主要分為以下幾個包:

其中,activity、adapter、fragment各自都有一個基類,做統一的處理,比如定義了一些共用的常量、物件和方法等。

介面層是最複雜,最容易變得混亂不堪,最容易出問題的層級。所以,從架構到程式碼,很多東西都需要設計好,以及規範好,才能保證程式易維護、易擴充套件。後續的文章裡將會詳細分享下我在這方面的經驗。

模型層

模型層橫跨所有層級,封裝了所有資料實體類,基本上也是跟json的obj資料一致的,在介面層會將obj轉化為相應的實體類,再通過Action傳到介面層。另外,模型層還定義了一些常量,比如使用者狀態、支付狀態等。在Api裡返回的是用1、2、3這樣定義的,而我則用列舉類定義了這些狀態。用列舉類定義,就可以避免了邊界的檢查,同時也更明瞭,誰會記得那麼多1、2、3都代表什麼狀態呢。然而用列舉類定義的話,就必須能將1、2、3轉化為相應的列舉常量。這裡,我提供兩種實現方式:

  1. 使用gson的@SerializedName標籤,比如0為FALSE,1為TRUE,則可以如下定義:
  1. 通過定義一個value,如下:

通過gson的方式,直接訪問TRUE或FALSE就會自動序列化為1或0;如果通過第二種方式,因為沒有序列化,則需要通過getValue方式獲取1或0。

結束

以上就是最基本的架構了,講得比較簡單,只列了幾個核心的東西。並沒有進一步去擴充套件,擴充套件是下一步的事情了,後續的文章裡會慢慢展開。

相關文章