基于RxJava2+Retrofit2精心打造的Android基礎(chǔ)框架XSnow

基于RxJava+Retrofit精心打造的Android基礎(chǔ)框架,包含網(wǎng)絡(luò)、上傳、下載、緩存、事件總線、權(quán)限管理、數(shù)據(jù)庫、圖片加載、UI模塊,基本都是項(xiàng)目中必用功能,每個模塊充分解耦,可隨意替換。
XSnow,X:未知一切,取其通用之意;Snow:雪,取其純凈之意。該框架通用純凈,只依賴公共核心庫。

網(wǎng)絡(luò)

簡介:

網(wǎng)絡(luò)算是項(xiàng)目的靈魂,基本每個項(xiàng)目都離不開網(wǎng)絡(luò),而一個簡單好用,又支持各種配置的網(wǎng)絡(luò)訪問庫就顯得尤為重要了。該模塊也是XSnow的核心功能,使用簡單,支持定制常用配置,如各種攔截器、緩存策略、請求頭等。

如果不進(jìn)行二次封裝,上層項(xiàng)目基于RxJava+Retrofit請求網(wǎng)絡(luò)時需要每個接口都寫一個服務(wù)接口,這樣非常不便利。如何將響應(yīng)結(jié)果通用處理就成為該模塊的重點(diǎn),項(xiàng)目中采用泛型轉(zhuǎn)換方式,將響應(yīng)結(jié)果ResponseBody通過map操作符轉(zhuǎn)換成需要的T,具體實(shí)現(xiàn)參考項(xiàng)目中http包下的func包,如果需要Http響應(yīng)碼,也可以將響應(yīng)結(jié)果包裝成Response<ResponseBody>這樣進(jìn)行轉(zhuǎn)換成T,考慮到項(xiàng)目中很少需要Http響應(yīng)碼來進(jìn)行判定,一般使用服務(wù)器自定義的響應(yīng)碼就可以了,故該模塊采用ResponseBody統(tǒng)一接收這種處理方式。

功能:

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

  • 全局配置支持CallAdapter.Factory、Converter.Factoryokhttp3.Call.Factory、SSLSocketFactory、HostnameVerifierConnectionPool、主機(jī)URL、請求頭、請求參數(shù)、代理、攔截器、Cookie、OKHttp緩存、連接超時時間、讀寫超時時間、失敗重試次數(shù)、失敗重試間隔時間的一系列配置。

  • 局部請求配置支持主機(jī)URL、請求后綴、請求頭、請求參數(shù)、攔截器、本地緩存策略、本地緩存時間、本地緩存key、連接超時時間、讀寫超時時間的一系列配置。

  • 支持OKHttp本身的Http緩存,也支持外部自定義的在線離線緩存,可配置緩存策略,共有五種緩存策略,如優(yōu)先獲取緩存策略,具體實(shí)現(xiàn)參考http包下的strategy包。

  • 支持請求與響應(yīng)統(tǒng)一處理,不需要上層每個模塊都定義請求服務(wù)接口。

  • 支持泛型T接收處理響應(yīng)數(shù)據(jù),也可根據(jù)服務(wù)器返回的統(tǒng)一數(shù)據(jù)模式定制如包含Code、Data、Message的通用Model ApiResult<T>。由于ApiResult的屬性不定,無法做到統(tǒng)一處理,所以單獨(dú)放到netexpand module中,里面包含與其相關(guān)的請求處理,可以根據(jù)該module定制屬于各自服務(wù)器的相關(guān)功能。

  • 支持異常統(tǒng)一處理,定制了ApiException攔截處理,統(tǒng)一返回異常信息。

  • 支持返回Observable,可繼續(xù)定制請求的相關(guān)特性,也支持返回回調(diào)的處理結(jié)果。

  • 支持失敗重試機(jī)制,可配置失敗重試次數(shù)以及重試時間間隔。

  • ......

使用示例:

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

ViseHttp.init(this);
ViseHttp.CONFIG()
        .baseUrl("http://10.8.4.39/")
        .setCookie(true)
        .converterFactory(GsonConverterFactory.create())
        .interceptor(new HttpLogInterceptor()
                .setLevel(HttpLogInterceptor.Level.BODY));

后面就是具體調(diào)用請求的過程,請求的類型有多種情形,下面就以最常用的幾種類型舉例說明,具體效果可以查看demo,以下為使用示例:

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

    @Override
    public void onFail(int errCode, String errMsg) {
    }
});
  • GET 帶緩存
ViseHttp.GET()
                .suffixUrl("getAuthor")
                .setLocalCache(true)
                .cacheMode(CacheMode.FIRST_CACHE) //配置緩存策略
                .request(mContext, new ACallback<CacheResult<AuthorModel>>() {
                    @Override
                    public void onSuccess(CacheResult<AuthorModel> cacheResult) {
                    }

                    @Override
                    public void onFail(int errCode, String errMsg) {
                    }
                });
  • GET 返回String
ViseHttp.GET().suffixUrl("getString").request(mContext, new ACallback<String>() {
    @Override
    public void onSuccess(String data) {
    }

    @Override
    public void onFail(int errCode, String errMsg) {
    }
});
  • GET 返回List
ViseHttp.GET().suffixUrl("getListAuthor").request(mContext, 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()).suffixUrl("getApiResultAuthor").request(mContext, new ACallback<AuthorModel>() {
    @Override
    public void onSuccess(AuthorModel authorModel) {
    }

    @Override
    public void onFail(int errCode, String errMsg) {
    }
});
  • POST 上傳表單
ViseHttp.BASE(new ApiPostRequest()
                .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)))
                .suffixUrl("postFormAuthor")
                .request(mContext, new ACallback<String>() {
                    @Override
                    public void onSuccess(String data) {
                    }

                    @Override
                    public void onFail(int errCode, String errMsg) {
                    }
                });
  • POST 上傳json
AuthorModel mAuthorModel = new AuthorModel();
mAuthorModel.setAuthor_id(1008);
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()
        .setJson(GSONUtil.gson().toJson(mAuthorModel)))
        .suffixUrl("postJsonAuthor")
        .request(mContext, new ACallback<String>() {
            @Override
            public void onSuccess(String data) {
            }

            @Override
            public void onFail(int errCode, String errMsg) {
            }
        });
  • POST 后綴帶請求參數(shù)
AuthorModel mAuthorModel = new AuthorModel();
mAuthorModel.setAuthor_id(1009);
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()
        .addUrlParam("appId", "10001")
        .addUrlParam("appType", "Android")
        .setJson(GSONUtil.gson().toJson(mAuthorModel)))
        .suffixUrl("postUrlAuthor")
        .request(mContext, new ACallback<String>() {
            @Override
            public void onSuccess(String data) {
            }

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

上傳下載

簡介:

該庫提供的上傳下載功能比較簡潔實(shí)用,基本能滿足單個線程下的常用相關(guān)操作,如果需要多線程和斷點(diǎn)續(xù)傳功能就需要上層實(shí)現(xiàn),也可以依賴如RxDownload庫。

功能:

  • 支持單文件和多文件上傳。

  • 支持每個文件都有對應(yīng)的回調(diào)進(jìn)度。

  • 支持傳入字節(jié)流或者字節(jié)數(shù)組進(jìn)行上傳。

  • 支持下載進(jìn)度回調(diào),每秒刷新下載進(jìn)度。

使用示例:

由于上傳下載功能需要用到網(wǎng)絡(luò)相關(guān),所以也需要像網(wǎng)絡(luò)那樣進(jìn)行初始化和添加全局配置。下面是上傳下載使用示例,具體效果可以查看demo。

  • 上傳示例:
ViseHttp.UPLOAD(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/")
        .suffixUrl("addImageFile")
        .request(mContext, new ACallback<Object>() {
    @Override
    public void onSuccess(Object data) {
    }

    @Override
    public void onFail(int errCode, String errMsg) {
    }
});
  • 下載示例:
ViseHttp.DOWNLOAD()
                .baseUrl("http://dldir1.qq.com/")
                .suffixUrl("weixin/android/weixin6330android920.apk")
                .setFileName(saveName)
                .request(mContext, new ACallback<DownProgress>() {
                    @Override
                    public void onSuccess(DownProgress downProgress) {
                    }

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

緩存

簡介:

包含內(nèi)存、磁盤二級緩存以及SharedPreferences緩存,可自由拓展。磁盤緩存支持KEY加密存儲,可定制緩存時長。SharedPreferences支持內(nèi)容安全存儲,采用Base64加密解密。

使用示例:

  • 內(nèi)存存儲:MemoryCache.getInstance().put("authorInfo", mAuthorModel);

  • 內(nèi)存獲?。?code>MemoryCache.getInstance().get("authorInfo");

  • 磁盤緩存存儲:diskCache.put("authorInfo", mAuthorModel);

  • 磁盤緩存獲取:diskCache.get("authorInfo");

  • SharedPreferences緩存存儲:spCache.put("authorInfo", mAuthorModel);

  • SharedPreferences緩存獲?。?code>spCache.get("authorInfo");

事件總線

簡介:

采用Rx響應(yīng)式編程思想建立的RxBus模塊,采用注解方式標(biāo)識事件消耗地,通過遍歷查找事件處理方法。支持可插拔,可替換成EventBus庫,只需上層采用的同樣是注解方式,那么上層是不需要動任何代碼的。

使用示例:

  • 發(fā)送事件: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());
    }
}

數(shù)據(jù)庫

簡介:

采用greenDao數(shù)據(jù)庫,其優(yōu)勢就不多說了,網(wǎng)上有解釋,其主要優(yōu)點(diǎn)就是性能高。該模塊定制數(shù)據(jù)庫操作接口,有統(tǒng)一的實(shí)現(xiàn)類DBManager,上層只需實(shí)現(xiàn)getAbstractDao()方法告知底層DaoSession,增刪改查操作不需要關(guān)心具體細(xì)節(jié),調(diào)用DBManager中的方法就行。

使用示例:

  • 配置:需要通過gradle添加greendao的相關(guān)插件配置,還有需要在當(dāng)前應(yīng)用module中的android配置下添加如下配置信息,具體可以參考demo的示例
greendao{
    schemaVersion 1 //數(shù)據(jù)庫版本
    targetGenDir 'src/main/java'    //包目錄所在文件夾
    daoPackage 'com.vise.snowdemo.db'   //存放數(shù)據(jù)庫相關(guān)的包目錄
}
  • 初始化:在application中進(jìn)行如下初始化操作:DbHelper.getInstance().init(this);

  • 增:DbHelper.getInstance().author().insert(mAuthorModel);

  • 刪:DbHelper.getInstance().author().delete(mAuthorModel);

  • 改:DbHelper.getInstance().author().update(mAuthorModel);

  • 查:DbHelper.getInstance().author().loadAll()

圖片加載

簡介:

采用Glide庫進(jìn)行圖片加載,支持輕量級圖片加載,該模塊支持可插拔,可根據(jù)需求替換成任意圖片加載庫,如果項(xiàng)目中對于圖片處理要求比較高,那么可以替換成Facebook提供的Fresco庫。

使用示例:

  • 初始化:在application中進(jìn)行如下初始化操作:LoaderFactory.getLoader().init(this);

  • 調(diào)用過程:

LoaderFactory.getLoader().loadNet(imageView, url, new ILoader.Options(R.mipmap.github_head_portrait, R.mipmap.github_head_portrait));

權(quán)限管理

簡介:

由于Android6.0以上系統(tǒng)對于權(quán)限管理更嚴(yán)格,安全性也有很大的提高,但是隨之帶來的就是權(quán)限管理的代碼編寫更麻煩,如在權(quán)限被用戶拒絕時該怎么提示,或者在用戶勾選永遠(yuǎn)拒絕下該怎么處理。針對此種情況,該模塊盡量以最小的調(diào)用完成權(quán)限的管理,只需要一行代碼就搞定權(quán)限的申請過程,并返回所有需要的回調(diào)結(jié)果。

使用示例:

//具體使用效果請查看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

簡介:

包含基礎(chǔ)組件、視圖狀態(tài)管理以及萬能適配器。適配器可滿足所有基于BaseAdapter的適配器組裝,使用方便,易拓展;視圖狀態(tài)管理包含空視圖、網(wǎng)絡(luò)異常、其他異常的重試以及視圖切換機(jī)制。

使用示例:

//創(chuàng)建視圖管理
mStatusLayoutManager = StatusLayoutManager.newBuilder(mContext)
        .contentView(R.layout.status_switch_content_layout)//配置內(nèi)容視圖
        .loadingView(R.layout.loading_layout)//配置加載視圖
        .emptyView(R.layout.empty_layout)//配置空視圖
        .networkErrorView(R.layout.network_error_layout)//配置網(wǎng)絡(luò)異常視圖
        .otherErrorView(R.layout.other_error_layout)//配置其他異常視圖
        .retryViewId(R.id.reload_view)//配置重試ViewID
        .onStatusViewListener(new OnStatusViewListener() {//配置狀態(tài)監(jiān)聽
            @Override
            public void onShowView(View view, int id) {//顯示
            }

            @Override
            public void onHideView(View view, int id) {//隱藏
            }
        })
        .onRetryListener(new OnRetryListener() {//配置重試監(jiān)聽
            @Override
            public void onRetry() {
                //模擬重試,顯示加載視圖
                mStatusLayoutManager.showLoadingView();
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            Thread.sleep(3000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                //加載成功,顯示內(nèi)容視圖
                                mStatusLayoutManager.showContentView();
                            }
                        });
                    }
                }).start();
            }
        }).build();
mLayoutMain.addView(mStatusLayoutManager.getStatusLayout());關(guān)聯(lián)根視圖
mStatusLayoutManager.showLoadingView();//顯示加載視圖

效果展示

主頁

菜單欄

?網(wǎng)絡(luò) GET方式請求

?網(wǎng)絡(luò) POST方式請求

上傳下載

圖片加載

狀態(tài)視圖切換

數(shù)據(jù)庫、緩存、事件總線

注:該框架引用了日志系統(tǒng)和公共工具庫,這兩個庫都很輕量級,具體使用詳情可分別參考
https://github.com/xiaoyaoyou1212/ViseLog
https://github.com/xiaoyaoyou1212/ViseUtils。

關(guān)于作者

作者:胡偉

網(wǎng)站:http://www.huwei.tech

博客:http://blog.csdn.net/xiaoyaoyou1212

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容