本庫是一款基于RxJava2+Retrofit2實現簡單易用的網絡請求框架,結合android平臺特性的網絡封裝庫,采用api鏈式調用一點到底,集成cookie管理,多種緩存模式,極簡https配置,上傳下載進度顯示,請求錯誤自動重試,請求攜帶token、時間戳、簽名sign動態配置,自動登錄成功后請求重發功能,3種層次的參數設置默認全局局部,默認標準ApiResult同時可以支持自定義的數據結構,已經能滿足現在的大部分網絡請求。
注:Retrofit和Rxjava是當下非?;鸨拈_源框架,均來自神一般的公司。本庫就不介紹Retrofit和Rxjava2的用法。
為什么會封裝此庫?
網上好的開源網絡庫像Volley、async-http、okhttp、retrofit等都非常強大,但是實際應用中我們不會直接去使用,一般都會根據自己的業務再封裝一層,這樣更方便快捷,又能統一處理業務共性的東西例如:統一的數據結構(code、msg、data)、token處理、網絡異常等情況。在使用retrofit來請求網絡的時候,項目的需求越來越多,api也隨之越來越多,一個普通的應用api一般也在100+左右。如果把這些api放在一個ApiService內會很臃腫,不利于查看api.如果采用模塊的方式對api進行分類,每個模塊對應若干個api.以retrofit的使用方式又需要創建若干個ApiService,這種方式維護方便,但是模塊增多了,類也增多了很多。對于懶人來說就想通過一個URL就能回調你所需要的數據,什么ApiService都不想理會,同時又可以很快的與自己的業務相關聯,就類似于代替你在開源網絡庫基礎上再封裝一層的作用,于是本庫就應運而生。
特點
?比Retrofit使用更簡單、更易用。
?采用鏈式調用一點到底
?加入基礎ApiService,減少Api冗余
?支持動態配置和自定義底層框架Okhttpclient、Retrofit.
?支持多種方式訪問網絡GET、POST、PUT、DELETE等請求協議
?支持網絡緩存,八種緩存策略可選,涵蓋大多數業務場景
?支持固定添加header和動態添加header
?支持添加全局參數和動態添加局部參數
?支持文件下載、多文件上傳和表單提交數據
?支持文件請求、上傳、下載的進度回調、錯誤回調,也可以自定義回調
?支持默認、全局、局部三個層次的配置功能
?支持任意數據結構的自動解析
?支持添加動態參數例如timeStamp時間戳、token、簽名sign
?支持自定義的擴展API
?支持多個請求合并
?支持Cookie管理
?支持異步、同步請求
?支持Https、自簽名網站Https的訪問、雙向驗證
?支持失敗重試機制,可以指定重試次數、重試間隔時間
?支持根據ky刪除網絡緩存和清空網絡緩存
?提供默認的標準ApiResult解析和回調,并且可自定義ApiResult
?支持取消數據請求,取消訂閱,帶有對話框的請求不需要手動取消請求,對話框消失會自動取消請求
?支持請求數據結果采用回調和訂閱兩種方式
?api設計上結合http協議和android平臺特點來實現,loading對話框,實時進度條顯示
?返回結果和異常統一處理
?結合RxJava2,線程智能控制
演示(請star支持)
RxEasyHttp與Rxjava結合使用場景演示
build.gradle設置
dependencies {
compile 'com.zhouyou:rxeasyhttp:2.0.8'
}
權限說明
如果使用本庫實現文件下載到SD卡、或者配置了緩存數據到SD卡,你必須要考慮到Android6.0及以上系統的運行時權限,給大家推薦兩個權限庫:
AndPermission
RxPermissions
因為要請求網絡、從SD卡讀寫緩存、下載文件到SD卡等等,所以需要在manifest.xml中配置以下幾個權限,如果你已經配置過了這些權限,請不要重復配置:
全局配置
一般在 Aplication,或者基類中,只需要調用一次即可,可以配置調試開關,全局的超時時間,公共的請求頭和請求參數等信息
初始化需要一個Context,最好在Application#onCreate()中初始化,記得在manifest.xml中注冊Application。
Application:
public class MyApplication extends Application {
@Override
public void onCreate() {super.onCreate();
}
}
manifest.xml:
...
android:name=".MyApplication"
...
/>
默認初始化
如果使用默認始化后,一切采用默認設置。如果你需要配置全局超時時間、緩存、Cookie、底層為OkHttp的話,請看高級初始化。
public class MyApplication extends Application {
@Override
public void onCreate() {super.onCreate();EasyHttp.init(this);//默認初始化
}
}
高級初始化
可以進行超時配置、網絡緩存配置、okhttp相關參數配置、retrofit相關參數配置、cookie配置等,這些參數可以選擇性的根據業務需要配置。
public class MyApplication extends Application {
@Override
public void onCreate() {super.onCreate();EasyHttp.init(this);//默認初始化,必須調用//全局設置請求頭HttpHeaders headers = new HttpHeaders();headers.put("User-Agent", SystemInfoUtils.getUserAgent(this, AppConstant.APPID));//全局設置請求參數HttpParams params = new HttpParams();params.put("appId", AppConstant.APPID);//以下設置的所有參數是全局參數,同樣的參數可以在請求的時候再設置一遍,那么對于該請求來講,請求中的參數會覆蓋全局參數EasyHttp.getInstance()//可以全局統一設置全局URL.setBaseUrl(Url)//設置全局URL url只能是域名 或者域名+端口號 // 打開該調試開關并設置TAG,不需要就不要加入該行// 最后的true表示是否打印內部異常,一般打開方便調試錯誤.debug("EasyHttp", true)//如果使用默認的60秒,以下三行也不需要設置.setReadTimeOut(60 * 1000).setWriteTimeOut(60 * 100).setConnectTimeout(60 * 100)//可以全局統一設置超時重連次數,默認為3次,那么最差的情況會請求4次(一次原始請求,三次重連請求),//不需要可以設置為0.setRetryCount(3)//網絡不好自動重試3次//可以全局統一設置超時重試間隔時間,默認為500ms,不需要可以設置為0.setRetryDelay(500)//每次延時500ms重試//可以全局統一設置超時重試間隔疊加時間,默認為0ms不疊加.setRetryIncreaseDelay(500)//每次延時疊加500ms//可以全局統一設置緩存模式,默認是不使用緩存,可以不傳,具體請看CacheMode.setCacheMode(CacheMode.NO_CACHE)//可以全局統一設置緩存時間,默認永不過期.setCacheTime(-1)//-1表示永久緩存,單位:秒 ,Okhttp和自定義RxCache緩存都起作用//全局設置自定義緩存保存轉換器,主要針對自定義RxCache緩存.setCacheDiskConverter(new SerializableDiskConverter())//默認緩存使用序列化轉化//全局設置自定義緩存大小,默認50M.setCacheMaxSize(100 * 1024 * 1024)//設置緩存大小為100M//設置緩存版本,如果緩存有變化,修改版本后,緩存就不會被加載。特別是用于版本重大升級時緩存不能使用的情況.setCacheVersion(1)//緩存版本為1//.setHttpCache(new Cache())//設置Okhttp緩存,在緩存模式為DEFAULT才起作用//可以設置https的證書,以下幾種方案根據需要自己設置.setCertificates() //方法一:信任所有證書,不安全有風險//.setCertificates(new SafeTrustManager()) //方法二:自定義信任規則,校驗服務端證書//配置https的域名匹配規則,不需要就不要加入,使用不當會導致https握手失敗//.setHostnameVerifier(new SafeHostnameVerifier())//.addConverterFactory(GsonConverterFactory.create(gson))//本框架沒有采用Retrofit的Gson轉化,所以不用配置.addCommonHeaders(headers)//設置全局公共頭.addCommonParams(params)//設置全局公共參數//.addNetworkInterceptor(new NoCacheInterceptor())//設置網絡攔截器//.setCallFactory()//局設置Retrofit對象Factory//.setCookieStore()//設置cookie//.setOkproxy()//設置全局代理//.setOkconnectionPool()//設置請求連接池//.setCallbackExecutor()//全局設置Retrofit callbackExecutor//可以添加全局攔截器,不需要就不要加入,錯誤寫法直接導致任何回調不執行//.addInterceptor(new GzipRequestInterceptor())//開啟post數據進行gzip后發送給服務器.addInterceptor(new CustomSignInterceptor());//添加參數簽名攔截器
}
}
請求數據
網絡請求,采用鏈式調用,支持一點到底。
入口方法
/**
* get請求*/
public static GetRequest get(String url);/*** post請求和文件上傳*/
public static PostRequest post(String url);/*** delete請求*/
public static DeleteRequest delete(String url) ;/*** 自定義請求*/
public static CustomRequest custom();/*** 文件下載*/
public static DownloadRequest downLoad(String url) ;/*** put請求*/
public static PutRequest put(String url);
通用功能配置
1.包含一次普通請求所有能配置的參數,真實使用時不需要配置這么多,按自己的需要選擇性的使用即可
2.以下配置全部是單次請求配置,不會影響全局配置,沒有配置的仍然是使用全局參數。
3.為單個請求設置超時,比如涉及到文件的需要設置讀寫等待時間多一點。
完整參數GET示例:
EasyHttp.get("/v1/app/chairdressing/skinAnalyzePower/skinTestResult")
.baseUrl("http://www.xxxx.com")//設置url.writeTimeOut(30*1000)//局部寫超時30s,單位毫秒.readTimeOut(30*1000)//局部讀超時30s,單位毫秒.connectTimeout(30*1000)//局部連接超時30s,單位毫秒.headers(new HttpHeaders("header1","header1Value"))//添加請求頭參數.headers("header2","header2Value")//支持添加多個請求頭同時添加.headers("header3","header3Value")//支持添加多個請求頭同時添加.params("param1","param1Value")//支持添加多個參數同時添加.params("param2","param2Value")//支持添加多個參數同時添加//.addCookie(new CookieManger(this).addCookies())//支持添加Cookie.cacheTime(300)//緩存300s 單位s.cacheKey("cachekey")//緩存key.cacheMode(CacheMode.CACHEANDREMOTE)//設置請求緩存模式//.okCache()//使用模式緩存模式時,走Okhttp緩存.cacheDiskConverter(new GsonDiskConverter())//GSON-數據轉換器//.certificates()添加證書.retryCount(5)//本次請求重試次數.retryDelay(500)//本次請求重試延遲時間500ms.addInterceptor(Interceptor)//添加攔截器.okproxy()//設置代理.removeHeader("header2")//移除頭部header2.removeAllHeaders()//移除全部請求頭.removeParam("param1").accessToken(true)//本次請求是否追加token.timeStamp(false)//本次請求是否攜帶時間戳.sign(false)//本次請求是否需要簽名.syncRequest(true)//是否是同步請求,默認異步請求。true:同步請求.execute(new CallBack<SkinTestResult>() {@Overridepublic void onStart() {//開始請求}@Overridepublic void onCompleted() {//請求完成}@Overridepublic void onError(ApiException e) {//請求錯誤}@Overridepublic void onSuccess(SkinTestResult response) {//請求成功}});
url
Url可以通過初始化配置的時候傳入EasyHttp.getInstance().setBaseUrl("http://www.xxx.com");
入口方法傳入: EasyHttp.get("/v1/app/chairdressing/skinAnalyzePower/skinTestResult").baseUrl("http://www.xxxx.com")
如果入口方法中傳入的url含有http或者https,則不會拼接初始化設置的baseUrl.
例如:EasyHttp.get("http://www.xxx.com/v1/app/chairdressing/skinAnalyzePower/skinTestResult")則setBaseUrl()和baseUrl()傳入的baseurl都不會被拼接。
注:EasyHttp.get/post/put/等采用拼接的用法時請注意,url要用/斜杠開頭,例如:EasyHttp.get("/v1/login") 正確 EasyHttp.get("v1/login") 錯誤
http請求參數
兩種設置方式
.params(HttpParams params)
.params("param1","param1Value")//添加參數鍵值對
HttpParams params = new HttpParams();
params.put("appId", AppConstant.APPID);
.addCommonParams(params)//設置全局公共參數
http請求頭
.headers(HttpHeaders headers)
.headers("header2","header2Value")//添加參數鍵值對
.addCommonHeaders(headers)//設置全局公共頭
普通網絡請求
支持get/post/delete/put等
鏈式調用的終點請求的執行方式有:execute(Classclazz) 、execute(Type type)、execute(CallBackcallBack)三種方式,都是針對標準的ApiResult
execute(CallBackcallBack)
1.EasyHttp(推薦)
示例:
方式一:
//EasyHttp.post("/v1/app/chairdressing/skinAnalyzePower/skinTestResult")
EasyHttp.get("/v1/app/chairdressing/skinAnalyzePower/skinTestResult")
.readTimeOut(30 * 1000)//局部定義讀超時.writeTimeOut(30 * 1000).connectTimeout(30 * 1000).params("name","張三").timeStamp(true).execute(new SimpleCallBack<SkinTestResult>() {@Overridepublic void onError(ApiException e) {showToast(e.getMessage());}@Overridepublic void onSuccess(SkinTestResult response) {if (response != null) showToast(response.toString());}});
2.手動創建請求對象
//GetRequest 、PostRequest、DeleteRequest、PutRequest
GetRequest request = new GetRequest("/v1/app/chairdressing/skinAnalyzePower/skinTestResult");
request.readTimeOut(30 * 1000)//局部定義讀超時.params("param1", "param1Value1").execute(new SimpleCallBack<SkinTestResult>() {@Overridepublic void onError(ApiException e) {}@Overridepublic void onSuccess(SkinTestResult response) {}});
execute(Classclazz)和execute(Type type)
execute(Classclazz)和execute(Type type)功能基本一樣,execute(Type type)主要是針對集合不能直接傳遞Class
EasyHttp.get(url)
.params("param1", "paramValue1").execute(SkinTestResult.class)//非常簡單直接傳目標class//.execute(new TypeToken<List<SectionItem>>() {}.getType())//Type類型.subscribe(new BaseSubscriber<SkinTestResult>() {@Overridepublic void onError(ApiException e) {showToast(e.getMessage());}@Overridepublic void onNext(SkinTestResult skinTestResult) {showToast(skinTestResult.toString());}});
請求返回Disposable
網絡請求會返回Disposable對象,方便取消網絡請求
Disposable disposable = EasyHttp.get("/v1/app/chairdressing/skinAnalyzePower/skinTestResult")
.params("param1", "paramValue1").execute(new SimpleCallBack<SkinTestResult>() {@Overridepublic void onError(ApiException e) {showToast(e.getMessage());}@Overridepublic void onSuccess(SkinTestResult response) {showToast(response.toString());}});//在需要取消網絡請求的地方調用,一般在onDestroy()中//EasyHttp.cancelSubscription(disposable);
帶有進度框的請求
帶有進度框的請求,可以設置對話框消失是否自動取消網絡和自定義對話框功能,具體參數作用請看請求回調講解
方式一:ProgressDialogCallBack
ProgressDialogCallBack帶有進度框的請求,可以設置對話框消失是否自動取消網絡和自定義對話框功能,具體參數作用請看自定義CallBack講解
IProgressDialog mProgressDialog = new IProgressDialog() {
@Overridepublic Dialog getDialog() {ProgressDialog dialog = new ProgressDialog(MainActivity.this);dialog.setMessage("請稍候...");return dialog;}};EasyHttp.get("/v1/app/chairdressing/").params("param1", "paramValue1").execute(new ProgressDialogCallBack<SkinTestResult>(mProgressDialog, true, true) {@Overridepublic void onError(ApiException e) {super.onError(e);//super.onError(e)必須寫不能刪掉或者忘記了//請求失敗}@Overridepublic void onSuccess(SkinTestResult response) {//請求成功}});
注:錯誤回調 super.onError(e);必須寫
方式二:ProgressSubscriber
IProgressDialog mProgressDialog = new IProgressDialog() {
@Overridepublic Dialog getDialog() {ProgressDialog dialog = new ProgressDialog(MainActivity.this);dialog.setMessage("請稍候...");return dialog;}};
EasyHttp.get(URL)
.timeStamp(true).execute(SkinTestResult.class).subscribe(new ProgressSubscriber<SkinTestResult>(this, mProgressDialog) {@Overridepublic void onError(ApiException e) {super.onError(e);showToast(e.getMessage());}@Overridepublic void onNext(SkinTestResult skinTestResult) {showToast(skinTestResult.toString());}});
請求返回Observable
通過網絡請求可以返回Observable,這樣就可以很好的通過Rxjava與其它場景業務結合處理,甚至可以通過Rxjava的connect()操作符處理多個網絡請求。例如:在一個頁面有多個網絡請求,如何在多個請求都訪問成功后再顯示頁面呢?這也是Rxjava強大之處。
注:目前通過execute(Classclazz)方式只支持標注的ApiResult結構,不支持自定義的ApiResult
示例:
Observable observable = EasyHttp.get(url)
.params("param1", "paramValue1").execute(SkinTestResult.class);observable.subscribe(new BaseSubscriber<SkinTestResult>() {@Overridepublic void onError(ApiException e) {showToast(e.getMessage());}@Overridepublic void onNext(SkinTestResult skinTestResult) {showToast(skinTestResult.toString());}});
文件下載
本庫提供的文件下載非常簡單,沒有提供復雜的下載方式例如:下載管理器、斷點續傳、多線程下載等,因為不想把本庫做重。如果復雜的下載方式,還請考慮其它下載方案。
文件目錄如果不指定,默認下載的目錄為/storage/emulated/0/Android/data/包名/files
文件名如果不指定,則按照以下規則命名:
1.首先檢查用戶是否傳入了文件名,如果傳入,將以用戶傳入的文件名命名
2.如果沒有傳入文件名,默認名字是時間戳生成的。
3.如果傳入了文件名但是沒有后綴,程序會自動解析類型追加后綴名
示例:
String url = "http://61.144.207.146:8081/b8154d3d-4166-4561-ad8d-7188a96eb195/2005/07/6c/076ce42f-3a78-4b5b-9aae-3c2959b7b1ba/kfid/2475751/qqlite_3.5.0.660_android_r108360_GuanWang_537047121_release_10000484.apk";
EasyHttp.downLoad(url).savePath("/sdcard/test/QQ").saveName("release_10000484.apk")//不設置默認名字是時間戳生成的.execute(new DownloadProgressCallBack<String>() {@Overridepublic void update(long bytesRead, long contentLength, boolean done) {int progress = (int) (bytesRead * 100 / contentLength);HttpLog.e(progress + "% ");dialog.setProgress(progress);if (done) {//下載完成}...}@Overridepublic void onStart() {//開始下載}@Overridepublic void onComplete(String path) {//下載完成,path:下載文件保存的完整路徑}@Overridepublic void onError(ApiException e) {//下載失敗}});
POST請求,上傳String、json、object、body、byte[]
一般此種用法用于與服務器約定的數據格式,當使用該方法時,params中的參數設置是無效的,所有參數均需要通過需要上傳的文本中指定,此外,額外指定的header參數仍然保持有效。
?.upString("這是要上傳的長文本數據!")//默認類型是:MediaType.parse("text/plain")
?如果你對請求頭有自己的要求,可以使用這個重載的形式,傳入自定義的content-type文本
upString("這是要上傳的長文本數據!", "application/xml") // 比如上傳xml數據,這里就可以自己指定請求頭
?upJson該方法與upString沒有本質區別,只是數據格式是json,通常需要自己創建一個實體bean或者一個map,把需要的參數設置進去,然后通過三方的Gson或者 fastjson轉換成json字符串,最后直接使用該方法提交到服務器。
.upJson(jsonObject.toString())//上傳json
?.upBytes(new byte[]{})//上傳byte[]
?.requestBody(body)//上傳自定義RequestBody
?.upObject(object)//上傳對象object 必須要增加.addConverterFactory(GsonConverterFactory.create())設置
1.upString、upJson、requestBody、upBytes、upObject五個方法不能同時使用,當前只能選用一個
2.使用upJson、upObject時候params、sign(true/false)、accessToken(true/false)、攔截器都不會起作用
示例:
HashMap params = new HashMap<>();
params.put("key1", "value1");
params.put("key2", "這里是需要提交的json格式數據");
params.put("key3", "也可以使用三方工具將對象轉成json字符串");
JSONObject jsonObject = new JSONObject(params);
RequestBody body=RequestBody.create(MediaType.parse("xxx/xx"),"內容");
EasyHttp.post("v1/app/chairdressing/news/favorite")
//.params("param1", "paramValue1")//不能使用params,upString 與 params 是互斥的,只有 upString 的數據會被上傳.upString("這里是要上傳的文本!")//默認類型是:MediaType.parse("text/plain")//.upString("這是要上傳的長文本數據!", "application/xml") // 比如上傳xml數據,這里就可以自己指定請求頭//.upJson(jsonObject.toString())//.requestBody(body)//.upBytes(new byte[]{})//.upObject(object).execute(new SimpleCallBack<String>() {@Overridepublic void onError(ApiException e) {showToast(e.getMessage());}@Overridepublic void onSuccess(String response) {showToast(response);}});
源碼地址:https://github.com/zhou-you/RxEasyHttp
原文地址:http://www.apkbus.com/blog-151006-78095.html
篇幅所限,完整內容可點擊左下角“閱讀原文”查看。
原文發布時間為:2018-06-28
本文作者:zhouy478319399
本文來自云棲社區合作伙伴“安卓巴士Android開發者門戶”,了解相關信息可以關注“安卓巴士Android開發者門戶”。
總結
以上是生活随笔為你收集整理的一款基于RxJava2+Retrofit2实现简单易用的网络请求框架的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。