IDE采用Android Studio,Demo實作的功能為使用者注冊、登入和展示一個券清單,資料采用我們現有項目的測試資料,接口也是我們項目中的測試接口。
實作上,在Android Studio分為了相應的四個子產品(Module):model、api、core、app。
model為模型層,api為接口層,core為核心層,app為界面層。
model、api、core這三個子產品的類型為library,app子產品的類型為application。
四個子產品之間的依賴設定為:model沒有任何依賴,接口層依賴了模型層,核心層依賴了模型層和接口層,界面層依賴了核心層和模型層。
項目搭建的步驟如下:
建立新項目,項目名稱為KAndroid,包名為com.keegan.kandroid。預設已建立了app子產品,檢視下app子產品下的build.gradle,會看到第一行為:
這行表明了app子產品是application類型的。
分别建立子產品model、api、core,Module Type都選為Android Library,在Add an activity to module頁面選擇Add No Activity,這三個子產品做為庫使用,并不需要界面。建立完之後,檢視相應子產品的build.gradle,會看到第一行為:
建立子產品之間的依賴關系。有兩種方法可以設定:
第一種:通過右鍵子產品,然後Open Module Settings,選擇子產品的Dependencies,點選左下方的加号,選擇Module dependency,最後選擇要依賴的子產品,下圖為api子產品添加了model依賴;
第二種:直接在子產品的build.gradle設定。打開build.gradle,在最後的dependencies一項裡面添加新的一行:compile project(':ModuleName'),比如app子產品添加對model子產品和core子產品依賴之後的dependencies如下:
通過上面兩種方式的任意一種,建立了子產品之間的依賴關系之後,每個子產品的build.gradle的dependencies項的結果将會如下:
model:
api:
core:
app:
業務對象模型統一存放于model子產品,是對業務資料的封裝,大部分都是從接口傳過來的對象,是以,其屬性也與接口傳回的對象屬性相一緻。在這個Demo裡,隻有一個業務對象模型,封裝了券的基本資訊,以下是該實體類的代碼:
在這個Demo裡,提供了4個接口:一個發送驗證碼的接口、一個注冊接口、一個登入接口、一個擷取券清單的接口。這4個接口具體如下:
發送驗證碼接口
URL:http://uat.b.quancome.com/platform/api
參數:
參數名
描述
類型
appKey
ANDROID_KCOUPON
String
method
service.sendSmsCode4Register
phoneNum
手機号碼
輸出樣例:
注冊接口
customer.registerByPhone
code
驗證碼
password
MD5加密密碼
登入接口
其他參數:
customer.loginByApp
loginName
登入名(手機号)
imei
手機imei串号
loginOS
系統,android為1
int
券清單
issue.listNewCoupon
currentPage
目前頁數
pageSize
每頁顯示數量
是以可以封裝成實體類,代碼如下:
上面4個接口,URL和appKey都是一樣的,用來差別不同接口的則是method字段,是以,URL和appKey可以統一定義,method則根據不同接口定義不同常量。而除去appKey和method,剩下的參數才是每個接口需要定義的參數。是以,對上面4個接口的定義如下:
Api的實作類則是ApiImpl了,實作類需要封裝好請求資料并向伺服器發起請求,并将響應結果的資料轉為ApiResonse傳回。而向伺服器發送請求并将響應結果傳回的處理則封裝到http引擎類去處理。另外,這裡引用了gson将json轉為對象。ApiImpl的實作代碼如下:
而http引擎類的實作如下:
至此,接口層的封裝就完成了。接下來再往上看看核心層吧。
核心層處于接口層和界面層之間,向下調用Api,向上提供Action,它的核心任務就是處理複雜的業務邏輯。先看看我對Action的定義:
首先,和Api接口對比就會發現,參數并不一緻。登入并沒有iemi和loginOS的參數,擷取券清單的參數裡也少了pageSize。這是因為,這幾個參數,跟界面其實并沒有直接關系。Action隻要定義好跟界面相關的就可以了,其他需要的參數,在具體實作時再去擷取。
另外,大部分action的處理都是異步的,是以,添加了回調監聽器ActionCallbackListener,回調監聽器的泛型則是傳回的對象資料類型,例如擷取券清單,傳回的資料類型就是List,沒有對象資料時則為Void。回調監聽器隻定義了成功和失敗的方法,如下:
接下來再看看Action的實作。首先,要擷取imei,那就需要傳入一個Context;另外,還需要loginOS和pageSize,這定義為常量就可以了;還有,要調用接口層,是以還需要Api執行個體。而接口的實作分為兩步,第一步做參數檢查,第二步用異步任務調用Api。具體實作如下:
簡單的實作代碼就是這樣,其實,這還有很多地方可以優化,比如,将參數為空的檢查、手機号有效性的檢查、數字型範圍的檢查等等,都可以抽成獨立的方法,進而減少重複代碼的編寫。異步任務裡的代碼也一樣,都是可以通過重構優化的。另外,需要擴充時,比如添加緩存,那就在調用Api之前處理。
核心層的邏輯就是這樣了。最後就到界面層了。
首先,界面層需要調用核心層的Action,而這會在整個應用級别都用到,是以,Action的執行個體最好放在Application裡。代碼如下:
另外,一個Activity的基類也是很有必要的,可以減少很多重複的工作。基類的代碼如下:
再看看登入的Activity:
登入頁的布局檔案則如下:
可以看到,EditText的id命名統一以edit開頭,而在Activity裡的控件變量名則以Edit結尾。按鈕的onClick也統一用toXXX的方式命名,明确表明這是一個将要做的動作。還有,string,dimen也都統一在相應的資源檔案裡按照相應的規範去定義。
注冊頁和登陸頁差不多,這裡就不展示代碼了。主要再看看券清單頁,因為用到了ListView,ListView需要添加擴充卡。實際上,擴充卡很多代碼都是可以複用的,是以,我抽象了一個擴充卡的基類,代碼如下:
這個抽象基類內建了設定資料的方法,每個具體的擴充卡類隻要再實作各自的getView方法就可以了。本Demo的券清單的擴充卡如下:
而券清單的Activity簡單實作如下:
終于寫完了,代碼也終于放上了github,為了讓人更容易了解,是以很多都比較簡單,沒有再進行擴充。
本文轉自ljianbing51CTO部落格,原文連結:http://blog.51cto.com/ljianbing/1733333 ,如需轉載請自行聯系原作者