欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
Android項目重構之路:架構篇

原創(chuàng )文章,轉載請注明:轉載自Keegan小鋼
微信訂閱號:keeganlee_me
寫(xiě)于2015-06-05


Android項目重構之路:架構篇
Android項目重構之路:界面篇
Android項目重構之路:實(shí)現篇


去年10月底換到了新公司,做移動(dòng)研發(fā)組的負責人,剛開(kāi)始接手android項目時(shí),發(fā)現該項目真的是一團糟。首先是其架構,是按功能模塊進(jìn)行劃分的,本來(lái)按模塊劃分也挺好的,可是,他卻分得太細,總共分為了17個(gè)模塊,而好幾個(gè)模塊也就只有兩三個(gè)類(lèi)而已。但應用本身其實(shí)比較簡(jiǎn)單,要按功能模塊來(lái)分的話(huà),最多五個(gè)模塊就夠了。另外,有好多模塊劃分也很模糊,也有很多類(lèi)按其功能其實(shí)可以屬于多個(gè)模塊的,也有些類(lèi)定義不明確,做了不該做的事。有時(shí)候,我要找一個(gè)界面的Activity,按照其功能應該屬于A(yíng)模塊的,可是在A(yíng)模塊里卻找不到,于是,我只好去AndroidManifest文件里找了,找到才發(fā)現原來(lái)在B模塊里。也有時(shí)候,我要找另一個(gè)界面的Activity,可我看遍了所有模塊,也沒(méi)看出這個(gè)界面應該屬于哪個(gè)模塊,沒(méi)法子,又只能去AndroidManifest文件里找了,找到才發(fā)現竟然在C模塊里。代碼也是又亂又臭,導致出現一大堆bug又不好找,改好一個(gè)bug又出現另一個(gè)。整個(gè)項目從架構到代碼都是又臭又亂,開(kāi)發(fā)人員只是不停地改bug,根本沒(méi)法做新功能,更別談擴展了。當時(shí),公司已經(jīng)有為不同客戶(hù)定制化app的需求,而現有的架構完全無(wú)法滿(mǎn)足這樣的需求。因此,我決定重構,搭建一個(gè)易維護、易擴展、可定制的項目。

我將項目分為了四個(gè)層級:模型層、接口層、核心層、界面層。模型層定義了所有的模型;接口層封裝了服務(wù)器提供的API;核心層處理所有業(yè)務(wù)邏輯;界面層就處理界面的展示。幾個(gè)層級之間的關(guān)系如下圖所示:


下面展開(kāi)說(shuō)明具體的每個(gè)層次:

接口層

接口層封裝了網(wǎng)絡(luò )底層的API,并提供給核心層調用。剛開(kāi)始,為了簡(jiǎn)單,該層的核心類(lèi)我只定義了4個(gè):

  1. PostEngine,請求引擎類(lèi),對請求的發(fā)送和響應結果進(jìn)行處理;

  2. Response,響應類(lèi),封裝了Http請求返回的數據結構;

  3. Api,接口類(lèi),定義了所有接口方法;

  4. ApiImpl,接口實(shí)現類(lèi),實(shí)現所有接口方法。

PostEngine將請求封裝好發(fā)送到服務(wù)器,并對響應結果的json數據轉化為Response對象返回。Response其實(shí)就是響應結果的json數據實(shí)體類(lèi),json數據是有固定結構的,分為三類(lèi),如下:

{'event': '0', 'msg': 'success'}{'event': '0', 'msg': 'success', 'obj':{...}}{'event': '0', 'msg': 'success', 'objList':[{...}, {...}], 'currentPage': 1, 'pageSize': 20, 'maxCount': 2, 'maxPage': 1}

event為返回碼,0表示成功,msg則是返回的信息,obj是返回的單個(gè)數據對象,objList是返回的數據對象數組,currentPage表示當前頁(yè),pageSize則表示當前頁(yè)最多對象數量,maxCount表示對象數據總量,maxPage表示總共有多少頁(yè)。根據此結構,Response基本的定義如下:

public class Response<T> {    private String event;    private String msg;    private T obj;    private T objList;    private int currentPage;    private int pageSize;    private int maxCount;    private int maxPage;    //getter和setter方法    ...    }

每個(gè)屬性名稱(chēng)都要與json數據對應的名稱(chēng)相一致,否則無(wú)法轉化。obj和objList用泛型則可以轉化為相應的具體對象了。

Api接口類(lèi)定義了所有的接口方法,方法定義類(lèi)似如下:

public Response<Void> login(String loginName, String password);public Response<VersionInfo> getLastVersion();public Response<List<Coupon>> listNewCoupon(int currentPage, int pageSize);

ApiImpl則實(shí)現所有Api接口了,實(shí)現代碼類(lèi)似如下:

@Overridepublic Response<Void> login(String loginName, String password) {    try {        String method = Api.LOGIN;        List<NameValuePair> params = new ArrayList<NameValuePair>();        params.add(new BasicNameValuePair('loginName', loginName));        params.add(new BasicNameValuePair('password', EncryptUtil.makeMD5(password)));        TypeToken<Response<Void>> typeToken = new TypeToken<Response<Void>>(){};        return postEngine.specialHandle(method, params, typeToken);    } catch (Exception e) {        //異常處理    }}

實(shí)現中將請求參數和返回的類(lèi)型定義好,調用PostEngine對象進(jìn)行處理。
接口層的核心基本上就是這些了。

核心層

核心層介于接口層和界面層之間,主要處理業(yè)務(wù)邏輯,集中做數據處理。向上,給界面層提供數據處理的接口,稱(chēng)為Action;向下,調用接口層向服務(wù)器請求數據。向上的Action中定義的方法類(lèi)似如下:

public void getCustomer(String loginName, CallbackListener<Customer> callbackListener);

這是一個(gè)獲取用戶(hù)信息的方法,因為需要向接口層請求服務(wù)器Api數據,所以添加了callback監聽(tīng)器,在callback里對返回的數據結果進(jìn)行操作。CallbackListener就定義了一個(gè)成功和一個(gè)失敗的方法,代碼如下:

public interface CallbackListener<T> {    /**     * 請求的響應結果為成功時(shí)調用     * @param data  返回的數據     */    public void onSuccess(T data);    /**     * 請求的響應結果為失敗時(shí)調用     * @param errorEvent 錯誤碼     * @param message    錯誤信息     */    public void onFailure(String errorEvent, String message);}

接口的實(shí)現基本分為兩步:

  1. 參數檢查,檢查參數的合法性,包括非空檢查、邊界檢查、有效性檢查等;

  2. 使用異步任務(wù)調用接口層的Api,返回響應結果。

需要注意的是,Action是面向界面的,界面上的數據可能需要根據不同情況調用不同的Api。
后續擴展可以在這里添加緩存,但也要視不同情況而定,比如有些變化太快的數據,添加緩存就不太適合了。

界面層

界面層處于最上層,其核心就是負責界面的展示。
因為公司有為不同商戶(hù)定制不同app的需求,因此,這里就需要建立多個(gè)app的界面,這是一個(gè)很麻煩的事情,還好,Android Studio提供了很方便的方法可以大大減少工作量,主要通過(guò)設置Gradle,不同app可以添加不同的productFlavors。
界面層package的定義我也并不按照舊版的功能模塊劃分,而根據不同類(lèi)型劃分,主要分為以下幾個(gè)包:


其中,activity、adapter、fragment各自都有一個(gè)基類(lèi),做統一的處理,比如定義了一些共用的常量、對象和方法等。
界面層是最復雜,最容易變得混亂不堪,最容易出問(wèn)題的層級。所以,從架構到代碼,很多東西都需要設計好,以及規范好,才能保證程序易維護、易擴展。后續的文章里將會(huì )詳細分享下我在這方面的經(jīng)驗。

模型層

模型層橫跨所有層級,封裝了所有數據實(shí)體類(lèi),基本上也是跟json的obj數據一致的,在接口層會(huì )將obj轉化為相應的實(shí)體類(lèi),再通過(guò)Action傳到界面層。另外,模型層還定義了一些常量,比如用戶(hù)狀態(tài)、支付狀態(tài)等。在A(yíng)pi里返回的是用1、2、3這樣定義的,而我則用枚舉類(lèi)定義了這些狀態(tài)。用枚舉類(lèi)定義,就可以避免了邊界的檢查,同時(shí)也更明了,誰(shuí)會(huì )記得那么多1、2、3都代表什么狀態(tài)呢。然而用枚舉類(lèi)定義的話(huà),就必須能將1、2、3轉化為相應的枚舉常量。這里,我提供兩種實(shí)現方式:

  1. 使用gson的@SerializedName標簽,比如0為FALSE,1為T(mén)RUE,則可以如下定義:

public enum BooleanType {    @SerializedName('0')    FALSE,    @SerializedName('1')    TRUE}
  1. 通過(guò)定義一個(gè)value,如下:

public enum BooleanType {    FALSE('0'),    TRUE('1');    private String value;    BooleanType(String value) {        this.value = value;    }    public String getValue() {        return value;    }}

通過(guò)gson的方式,直接訪(fǎng)問(wèn)TRUE或FALSE就會(huì )自動(dòng)序列化為1或0;如果通過(guò)第二種方式,因為沒(méi)有序列化,則需要通過(guò)getValue方式獲取1或0。

結束

以上就是最基本的架構了,講得比較簡(jiǎn)單,只列了幾個(gè)核心的東西。并沒(méi)有進(jìn)一步去擴展,擴展是下一步的事情了,后續的文章里會(huì )慢慢展開(kāi)。


本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
探秘Hybrid APP開(kāi)發(fā)利器
hessian教程
thinkphp 寫(xiě)APP接口集成極光推送的例子
Android Settings模塊分析
新浪接口A(yíng)PI調用
UChome 代碼分析講解:uc_client模塊的client.php文件
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久