天天看點

基于RxJava2+Retrofit2精心打造的Android基礎架構XSnow

代碼位址如下:

http://www.demodashi.com/demo/12132.html

XSnow

基于RxJava2+Retrofit2精心打造的Android基礎架構,包含網絡、上傳、下載下傳、緩存、事件總線、權限管理、資料庫、圖檔加載、UI子產品,基本都是項目中必用功能,每個子產品充分解耦,可自由拓展。

XSnow,X:未知一切,取其通用之意;Snow:雪,取其純淨之意。該架構通用純淨,隻依賴公共核心庫。

  • 項目依賴:

    compile 'com.vise.xiaoyaoyou: xsnow:2.1.4'

效果展示

![操作示範動畫]

基于RxJava2+Retrofit2精心打造的Android基礎架構XSnow

項目結構

基于RxJava2+Retrofit2精心打造的Android基礎架構XSnow

網絡

簡介:

網絡算是項目的靈魂,基本每個項目都離不開網絡,而一個簡單好用,又支援各種配置的網絡通路庫就顯得尤為重要了。該子產品也是XSnow的核心功能,使用簡單,支援定制常用配置,如各種攔截器、緩存政策、請求頭等。

如果不進行二次封裝,上層項目基于RxJava+Retrofit請求網絡時需要每個接口都寫一個服務接口,這樣非常不便利。如何将響應結果通用處理就成為該子產品的重點,項目中采用泛型轉換方式,将響應結果ResponseBody通過map操作符轉換成需要的T,具體實作參考項目中http包下的func包,如果需要Http響應碼,也可以将響應結果包裝成Response這樣進行轉換成T,考慮到項目中很少需要Http響應碼來進行判定,一般使用伺服器自定義的響應碼就可以了,故該子產品采用ResponseBody統一接收這種處理方式。

功能:

  • 支援全局配置和單個請求的局部配置,如果局部配置與全局配置沖突,那麼局部配置會替換全局配置。
  • 全局配置支援

    CallAdapter.Factory

    Converter.Factory

    okhttp3.Call.Factory

    SSLSocketFactory

    HostnameVerifier

    ConnectionPool

    、主機URL、請求頭、請求參數、代理、攔截器、Cookie、OKHttp緩存、連接配接逾時時間、讀寫逾時時間、失敗重試次數、失敗重試間隔時間的一系列配置。
  • 局部請求配置支援主機URL、請求字尾、請求頭、請求參數、攔截器、本地緩存政策、本地緩存時間、本地緩存key、連接配接逾時時間、讀寫逾時時間的一系列配置。
  • 支援OKHttp本身的Http緩存,也支援外部自定義的線上離線緩存,可配置緩存政策,共有五種緩存政策,如優先擷取緩存政策,具體實作參考http包下的strategy包。
  • 支援請求與響應統一處理,不需要上層每個子產品都定義請求服務接口。
  • 支援泛型T接收處理響應資料,也可根據伺服器傳回的統一資料模式定制如包含Code、Data、Message的通用Model ApiResult。由于ApiResult的屬性不定,無法做到統一處理,是以單獨放到netexpand module中,裡面包含與其相關的請求處理,可以根據該module定制屬于各自伺服器的相關功能。
  • 支援異常統一處理,定制了ApiException攔截處理,統一傳回異常資訊。
  • 支援傳回Observable,可繼續定制請求的相關特性,也支援傳回回調的處理結果。
  • 支援失敗重試機制,可配置失敗重試次數以及重試時間間隔。
  • 支援根據Tag中途取消請求,也可以取消所有請求。
  • ……

使用示例:

第一步需要在application中進行全局初始化以及添加全局相關配置,具體使用如下:

ViseHttp.init(this);
ViseHttp.CONFIG()
        //配置請求主機位址
        .baseUrl("http://192.168.1.100/")
        //配置全局請求頭
        .globalHeaders(new HashMap<String, String>())
        //配置全局請求參數
        .globalParams(new HashMap<String, String>())
        //配置讀取逾時時間,機關秒
        .readTimeout()
        //配置寫入逾時時間,機關秒
        .writeTimeout()
        //配置連接配接逾時時間,機關秒
        .connectTimeout()
        //配置請求失敗重試次數
        .retryCount()
        //配置請求失敗重試間隔時間,機關毫秒
        .retryDelayMillis()
        //配置是否使用cookie
        .setCookie(true)
        //配置自定義cookie
        .apiCookie(new ApiCookie(this))
        //配置是否使用OkHttp的預設緩存
        .setHttpCache(true)
        //配置OkHttp緩存路徑
        .setHttpCacheDirectory(new File(ViseHttp.getContext().getCacheDir(), ViseConfig.CACHE_HTTP_DIR))
        //配置自定義OkHttp緩存
        .httpCache(new Cache(new File(ViseHttp.getContext().getCacheDir(), ViseConfig.CACHE_HTTP_DIR), ViseConfig.CACHE_MAX_SIZE))
        //配置自定義離線緩存
        .cacheOffline(new Cache(new File(ViseHttp.getContext().getCacheDir(), ViseConfig.CACHE_HTTP_DIR), ViseConfig.CACHE_MAX_SIZE))
        //配置自定義線上緩存
        .cacheOnline(new Cache(new File(ViseHttp.getContext().getCacheDir(), ViseConfig.CACHE_HTTP_DIR), ViseConfig.CACHE_MAX_SIZE))
        //配置開啟Gzip請求方式,需要伺服器支援
        .postGzipInterceptor()
        //配置應用級攔截器
        .interceptor(new HttpLogInterceptor()
                .setLevel(HttpLogInterceptor.Level.BODY))
        //配置網絡攔截器
        .networkInterceptor(new NoCacheInterceptor())
        //配置轉換工廠
        .converterFactory(GsonConverterFactory.create())
        //配置擴充卡工廠
        .callAdapterFactory(RxJava2CallAdapterFactory.create())
        //配置請求工廠
        .callFactory(new Call.Factory() {
            @Override
            public Call newCall(Request request) {
                return null;
            }
        })
        //配置連接配接池
        .connectionPool(new ConnectionPool())
        //配置主機證書驗證
        .hostnameVerifier(new SSLUtil.UnSafeHostnameVerifier("http://192.168.1.100/"))
        //配置SSL證書驗證
        .SSLSocketFactory(SSLUtil.getSslSocketFactory(null, null, null))
        //配置主機代理
        .proxy(new Proxy(Proxy.Type.HTTP, new SocketAddress() {}));
           

後面就是具體調用請求的過程,請求的類型有多種情形,下面就以最常用的幾種類型舉例說明,具體效果可以檢視demo,以下為使用示例:

  • GET 不帶緩存
ViseHttp.GET("getAuthor").request(new ACallback<AuthorModel>() {
    @Override
    public void onSuccess(AuthorModel authorModel) {
    }

    @Override
    public void onFail(int errCode, String errMsg) {
    }
});
           

提供了多種參數的添加方式,具體可檢視BaseRequest中提供的API。

  • GET 帶緩存
ViseHttp.GET("getAuthor")
        .setLocalCache(true)//設定是否使用緩存,如果使用緩存必須設定為true
        .cacheMode(CacheMode.FIRST_CACHE) //配置緩存政策
        .request(new ACallback<CacheResult<AuthorModel>>() {
            @Override
            public void onSuccess(CacheResult<AuthorModel> cacheResult) {
            }

            @Override
            public void onFail(int errCode, String errMsg) {
            }
        });
           

由于帶緩存方式有點不一樣,需要告知上層是否是緩存資料,是以需要外部包裹一層CacheResult結構,使用時必須要按照這種方式設定model,還有需要注意的是必須要設定緩存開關為true,如果為false是沒法解析CacheResult結構的,這點一定切記。

  • GET 傳回String
ViseHttp.GET("getString").request(new ACallback<String>() {
    @Override
    public void onSuccess(String data) {
    }

    @Override
    public void onFail(int errCode, String errMsg) {
    }
});
           
  • GET 傳回List
ViseHttp.GET("getListAuthor").request(new ACallback<List<AuthorModel>>() {
    @Override
    public void onSuccess(List<AuthorModel> authorModel) {
    }

    @Override
    public void onFail(int errCode, String errMsg) {
    }
});
           
  • GET 傳回ApiResult
ViseHttp.BASE(new ApiGetRequest("getApiResultAuthor")).request(new ACallback<AuthorModel>() {
    @Override
    public void onSuccess(AuthorModel authorModel) {
    }

    @Override
    public void onFail(int errCode, String errMsg) {
    }
});
           

由于ApiResult這個結構沒法通用,用的是拓展庫方式提供一種解決方案,可替換成各自伺服器定義的字段,具體參考netexpand庫,這裡使用需要通過BASE将自定義的請求方式設定進去,内部會自動去掉外部層級ApiResult,直接傳回你所需的資料部分。

  • POST 上傳表單
ViseHttp.BASE(new ApiPostRequest("postFormAuthor")
        .addForm("author_name", getString(R.string.author_name))
        .addForm("author_nickname", getString(R.string.author_nickname))
        .addForm("author_account", "xiaoyaoyou1212")
        .addForm("author_github", "https://github.com/xiaoyaoyou1212")
        .addForm("author_csdn", "http://blog.csdn.net/xiaoyaoyou1212")
        .addForm("author_websit", "http://www.huwei.tech/")
        .addForm("author_introduction", getString(R.string.author_introduction)))
        .request(new ACallback<String>() {
            @Override
            public void onSuccess(String data) {
            }

            @Override
            public void onFail(int errCode, String errMsg) {
            }
        });
           

上傳表單時需要通過addForm将鍵值對一個個添加進去,支援上傳中文字元。

  • POST 上傳json
AuthorModel mAuthorModel = new AuthorModel();
mAuthorModel.setAuthor_id();
mAuthorModel.setAuthor_name(getString(R.string.author_name));
mAuthorModel.setAuthor_nickname(getString(R.string.author_nickname));
mAuthorModel.setAuthor_account("xiaoyaoyou1212");
mAuthorModel.setAuthor_github("https://github.com/xiaoyaoyou1212");
mAuthorModel.setAuthor_csdn("http://blog.csdn.net/xiaoyaoyou1212");
mAuthorModel.setAuthor_websit("http://www.huwei.tech/");
mAuthorModel.setAuthor_introduction(getString(R.string.author_introduction));
ViseHttp.BASE(new ApiPostRequest("postJsonAuthor")
        .setJson(GSONUtil.gson().toJson(mAuthorModel)))
        .request(new ACallback<String>() {
            @Override
            public void onSuccess(String data) {
            }

            @Override
            public void onFail(int errCode, String errMsg) {
            }
        });
           

上傳JSON格式資料時需要先将資料轉換成JSON格式,再通過setJson添加進去。

  • POST 字尾帶請求參數
AuthorModel mAuthorModel = new AuthorModel();
mAuthorModel.setAuthor_id();
mAuthorModel.setAuthor_name(getString(R.string.author_name));
mAuthorModel.setAuthor_nickname(getString(R.string.author_nickname));
mAuthorModel.setAuthor_account("xiaoyaoyou1212");
mAuthorModel.setAuthor_github("https://github.com/xiaoyaoyou1212");
mAuthorModel.setAuthor_csdn("http://blog.csdn.net/xiaoyaoyou1212");
mAuthorModel.setAuthor_websit("http://www.huwei.tech/");
mAuthorModel.setAuthor_introduction(getString(R.string.author_introduction));
ViseHttp.BASE(new ApiPostRequest("postUrlAuthor")
        .addUrlParam("appId", "10001")
        .addUrlParam("appType", "Android")
        .setJson(GSONUtil.gson().toJson(mAuthorModel)))
        .request(new ACallback<String>() {
            @Override
            public void onSuccess(String data) {
            }

            @Override
            public void onFail(int errCode, String errMsg) {
            }
        });
           

有些POST請求可能URL後面也帶有參數,這樣的話需要通過addUrlParam進行設定,與添加到請求body的參數設定方式addParam是不一樣的,這點需要注意。

上傳下載下傳

簡介:

該庫提供的上傳下載下傳功能比較簡潔實用,基本能滿足單個線程下的常用相關操作,如果需要多線程和斷點續傳功能就需要上層實作,也可以依賴如RxDownload庫。

功能:

  • 支援單檔案和多檔案上傳。
  • 支援每個檔案都有對應的回調進度。
  • 支援傳入位元組流或者位元組數組進行上傳。
  • 支援下載下傳進度回調,每秒重新整理下載下傳進度。

使用示例:

由于上傳下載下傳功能需要用到網絡相關,是以也需要像網絡那樣進行初始化和添加全局配置。下面是上傳下載下傳使用示例,具體效果可以檢視demo。

  • 上傳示例:
ViseHttp.UPLOAD("addImageFile", new UCallback() {
    @Override
    public void onProgress(long currentLength, long totalLength, float percent) {
    }

    @Override
    public void onFail(int errCode, String errMsg) {
    }}).addFile("androidIcon", getUploadFile(mContext, "test.jpg"))
        .baseUrl("https://200.200.200.50/")
        .request(new ACallback<Object>() {
    @Override
    public void onSuccess(Object data) {
    }

    @Override
    public void onFail(int errCode, String errMsg) {
    }
});
           

由于API請求成功與上傳回調沒法統一處理,故将請求成功與上傳進度回調分離,上傳進度通過UCallback告知調用者,上傳進度支援攔截器傳回,也支援添加檔案上傳時設定回調。

  • 下載下傳示例:
ViseHttp.DOWNLOAD("weixin/android/weixin6330android920.apk")
        .baseUrl("http://dldir1.qq.com/")
        .setFileName(saveName)
        .request(new ACallback<DownProgress>() {
            @Override
            public void onSuccess(DownProgress downProgress) {
            }

            @Override
            public void onFail(int errCode, String errMsg) {
            }
        });
           

通過讀取傳回的DownProgress擷取下載下傳進度,下載下傳檔案預設儲存在該應用的/cache/download目錄下。

緩存

簡介:

包含記憶體、磁盤二級緩存以及SharedPreferences緩存,可自由拓展。磁盤緩存支援KEY加密存儲,可定制緩存時長。SharedPreferences支援内容安全存儲,采用Base64加密解密。

使用示例:

  • 記憶體存儲:

    MemoryCache.getInstance().put("authorInfo", mAuthorModel);

  • 記憶體擷取:

    MemoryCache.getInstance().get("authorInfo");

  • 磁盤緩存存儲:

    diskCache.put("authorInfo", mAuthorModel);

  • 磁盤緩存擷取:

    diskCache.get("authorInfo");

  • SharedPreferences緩存存儲:

    spCache.put("authorInfo", mAuthorModel);

  • SharedPreferences緩存擷取:

    spCache.get("authorInfo");

事件總線

簡介:

采用Rx響應式程式設計思想建立的RxBus子產品,采用注解方式辨別事件消耗地,通過周遊查找事件處理方法。支援可插拔,可替換成EventBus庫,隻需上層采用的同樣是注解方式,那麼上層是不需要動任何代碼的。

使用示例:

  • 發送事件:

    BusFactory.getBus().post(new AuthorEvent().setAuthorModel(mAuthorModel));

  • 注冊事件:

    BusFactory.getBus().register(this);

  • 取消注冊:

    BusFactory.getBus().unregister(this);

  • 接收事件:
@EventSubscribe
public void showAuthor(IEvent event) {
    if (event != null && event instanceof AuthorEvent) {
        ViseLog.i("Receive Event Message:" + ((AuthorEvent) event).getAuthorModel());
    }
}
           

如果需要定制使用其他Bus如EventBus,那麼隻需将實作IBus接口的對象在應用初始化時通過

BusFactory.setBus(new EventBus())

傳進去即可。

資料庫

簡介:

采用greenDao資料庫,其優勢就不多說了,網上有解釋,其主要優點就是性能高。該子產品定制資料庫操作接口,有統一的實作類DBManager,上層隻需實作getAbstractDao()方法告知底層DaoSession,增删改查操作不需要關心具體細節,調用DBManager中的方法就行。

使用示例:

  • 配置:需要通過gradle添加greendao的相關插件配置,還有需要在目前應用module中的android配置下添加如下配置資訊,具體可以參考demo的示例
greendao{
    schemaVersion  //資料庫版本
    targetGenDir 'src/main/java'    //包目錄所在檔案夾
    daoPackage 'com.vise.snowdemo.db'   //存放資料庫相關的包目錄
}
           
  • 初始化:在application中進行如下初始化操作:

    DbHelper.getInstance().init(this);

  • 增:

    DbHelper.getInstance().author().insert(mAuthorModel);

  • 删:

    DbHelper.getInstance().author().delete(mAuthorModel);

  • 改:

    DbHelper.getInstance().author().update(mAuthorModel);

  • 查:

    DbHelper.getInstance().author().loadAll()

圖檔加載

簡介:

采用Glide庫進行圖檔加載,支援輕量級圖檔加載,該子產品支援可插拔,可根據需求替換成任意圖檔加載庫,如果項目中對于圖檔處理要求比較高,那麼可以替換成Facebook提供的Fresco庫。

使用示例:

  • 初始化:在application中進行如下初始化操作:

    LoaderFactory.getLoader().init(this);

  • 調用過程:

如果需要定制使用其他圖檔加載架構如Fresco,那麼隻需将實作ILoader接口的對象在應用初始化時通過

LoaderFactory.setLoader(new FrescoLoader())

傳進去即可。

權限管理

簡介:

由于Android6.0以上系統對于權限管理更嚴格,安全性也有很大的提高,但是随之帶來的就是權限管理的代碼編寫更麻煩,如在權限被使用者拒絕時該怎麼提示,或者在使用者勾選永遠拒絕下該怎麼處理。針對此種情況,該子產品盡量以最小的調用完成權限的管理,隻需要一行代碼就搞定權限的申請過程,并傳回所有需要的回調結果。

使用示例:

//具體使用效果請檢視demo
PermissionManager.instance().with(this).request(new OnPermissionCallback() {
    @Override
    public void onRequestAllow(String permissionName) {
        DialogUtil.showTips(mContext, getString(R.string.permission_control),
                getString(R.string.permission_allow) + "\n" + permissionName);
    }

    @Override
    public void onRequestRefuse(String permissionName) {
        DialogUtil.showTips(mContext, getString(R.string.permission_control),
                getString(R.string.permission_refuse) + "\n" + permissionName);
    }

    @Override
    public void onRequestNoAsk(String permissionName) {
        DialogUtil.showTips(mContext, getString(R.string.permission_control),
                getString(R.string.permission_noAsk) + "\n" + permissionName);
    }
}, Manifest.permission.CALL_PHONE);
           

UI

簡介:

包含基礎元件、視圖狀态管理以及萬能擴充卡。擴充卡可滿足所有基于BaseAdapter的擴充卡組裝,使用友善,易拓展;視圖狀态管理包含空視圖、網絡異常、其他異常的重試以及視圖切換機制。

使用示例:

//建立視圖管理
mStatusLayoutManager = StatusLayoutManager.newBuilder(mContext)
        .contentView(R.layout.status_switch_content_layout)//配置内容視圖
        .loadingView(R.layout.loading_layout)//配置加載視圖
        .emptyView(R.layout.empty_layout)//配置空視圖
        .networkErrorView(R.layout.network_error_layout)//配置網絡異常視圖
        .otherErrorView(R.layout.other_error_layout)//配置其他異常視圖
        .retryViewId(R.id.reload_view)//配置重試ViewID
        .onStatusViewListener(new OnStatusViewListener() {//配置狀态監聽
            @Override
            public void onShowView(View view, int id) {//顯示
            }

            @Override
            public void onHideView(View view, int id) {//隐藏
            }
        })
        .onRetryListener(new OnRetryListener() {//配置重試監聽
            @Override
            public void onRetry() {
                //模拟重試,顯示加載視圖
                mStatusLayoutManager.showLoadingView();
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            Thread.sleep();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                //加載成功,顯示内容視圖
                                mStatusLayoutManager.showContentView();
                            }
                        });
                    }
                }).start();
            }
        }).build();
mLayoutMain.addView(mStatusLayoutManager.getStatusLayout());關聯根視圖
mStatusLayoutManager.showLoadingView();//顯示加載視圖
           

基于RxJava2+Retrofit2精心打造的Android基礎架構

代碼位址如下:

http://www.demodashi.com/demo/12132.html

注:本文著作權歸作者,由demo大師發表,拒絕轉載,轉載需要作者授權