根據 RxJava2 和 Retrofit2 進行的封裝骗绕,進行網絡請求更加方便圆雁。
demo下載地址:https://github.com/sundevin/rxjava2_retrofit2
目前實現:
1, 統一風格的接口
2, 不統一風格的接口
3, 內存泄漏問題
4, 請求過程中 ProgressDialog
5, 自定義證書的 Https 的封裝
6, 使用 okHttp 進行下載時進度回調的封裝
后面將實現帶進度回調的上傳功能。
針對 Restful 風格的接口可以直接指定泛型嗜暴;
內部增加了 StringConverterFactory耸棒,非 Restful 風格的接口(如一些第三方接口的數據)可以直接獲取到 String,自行進行數據解析;
網絡請求過程中可以綁定到當前的 Activity, Activity 關閉的時候會主動停止請求橡淆,避免內存泄漏。也可決定是否顯示 ProgressDialog母赵;
數據請求前后可以打印 request 和 response 信息逸爵,更直觀的進行接口調試;
對 https 進行了封裝凹嘲,只需要指定自簽名證書即可师倔。
在使用 okHttp 請求的時候,支持進度回調和取消下載周蹭。
初始配置
1,項目依賴
compile 'io.reactivex.rxjava2:rxjava:2.0.7'
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
compile 'com.squareup.retrofit2:retrofit:2.2.0'
compile 'com.squareup.retrofit2:converter-gson:2.2.0'
compile 'com.squareup.retrofit2:adapter-rxjava2:2.2.0'
compile 'com.trello.rxlifecycle2:rxlifecycle:2.0.1'
// If you want to bind to Android-specific lifecycles
compile 'com.trello.rxlifecycle2:rxlifecycle-android:2.0.1'
// If you want pre-written Activities and Fragments you can subclass as providers
compile 'com.trello.rxlifecycle2:rxlifecycle-components:2.0.1'
運行時可能會有依賴錯誤趋艘,在 androidTestCompile 配置如下即可解決
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
exclude group: 'com.google.code.findbugs', module: 'jsr305'
})
2,OkHttp 配置
CustomHttpsTrust customHttpsTrust = new CustomHttpsTrust(CertificateManager.trustedCertificatesInputStream());
okHttpClient = new OkHttpClient.Builder()
.connectTimeout(CONNECT_TIMEOUT, TimeUnit.SECONDS)
.readTimeout(READ_TIMEOUT, TimeUnit.SECONDS)
.writeTimeout(WRITE_TIMEOUT, TimeUnit.SECONDS)
.addInterceptor(new HeaderInterceptor()) //添加 header
.addInterceptor(new LoggingInterceptor()) //請求信息的打印 ,可在 release 時關閉
.sslSocketFactory(customHttpsTrust.sSLSocketFactory, customHttpsTrust.x509TrustManager)// https 配置
.build();
3,Retrofit 配置
static {
retrofit = new Retrofit.Builder()
.baseUrl(ApiService.BASE_URL)//配置 baseUrl
.client(OkHttpHelper.getClient())
.addConverterFactory(StringConverterFactory.create()) //String 轉換
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.validateEagerly(true)
.build();
}
Restful 接口
以 demo 中后臺返回的標準數據為例凶朗,
result
為 obj
時:
{
"state":1,
"msg":"success",
"result":{}
}
result 為數組時:
{
"state":1,
"msg":"success",
"result":[]
}
其中 state
為1時表示業(yè)務處理成功瓷胧,數據正確。反之業(yè)務處理有誤棚愤,用msg
進行提示搓萧。
則建立 Entity 如下:
public class HttpResponseResult<T> {
private static final int SUCCESS_STATUS = 1;
private String msg;
private Integer state;
private T result;
public boolean isSuccess() {
return state != null && state == SUCCESS_STATUS;
}
public String getMsg() {
return msg;
}
public Integer getState() {
return state;
}
public T getResult() {
return result;
}
@Override
public String toString() {
return "HttpResponse{" +
"msg='" + msg + '\'' +
", state=" + state +
", result=" + result +
'}';
}
}
Object的請求:
/**
* post test
* @param map
* @return
*/
@POST("/muses-rest/java/rest/viewlogistics/"+CHANEL)
Observable<HttpResponseResult<LogisticsInfo>> getLogisticsInfo(@Body Map<String,Object> map);
開始請求:
Map<String, Object> map = new HashMap<>();
map.put("logisticsid", 20);
map.put("logisticsno", "1000817443587");
ServiceManager
.getApiService()
.getLogisticsInfo(map)
.compose(MainActivity.this.<HttpRespResult<LogisticsInfo>>bindToLifecycle())
.compose(TransformerHelper.<LogisticsInfo>transformer())
.compose(new DialogTransformer(MainActivity.this).<HttpRespResult<LogisticsInfo>>showDialog())
.subscribe(new CommonObserver<LogisticsInfo>() {
@Override
protected void onSuccess(LogisticsInfo logisticsInfo) {
Logger.e(logisticsInfo.toString());
}
});
List的請求:
@POST("/muses-rest/java/rest/viewlogistics/"+CHANEL)
Observable<HttpResponseResult<LogisticsInfo>> getLogisticsInfo(@Body Map<String,Object> map);
開始請求:
ServiceManager
.getApiService()
.testGet2()
.compose(MainActivity.this.<HttpRespResult<List<String>>>bindToLifecycle())
.compose(TransformerHelper.<List<String>>transformer())
.compose(new DialogTransformer(MainActivity.this).<HttpRespResult<List<String>>>showDialog())
.subscribe(new CommonObserver<List<String>>() {
@Override
protected void onSuccess(List<String> stringList) {
String[] str = stringList.toArray(new String[stringList.size()]);
Logger.e(Arrays.toString(str));
}
});
注意三個 compose 操作符的順序不要亂了,否則會出現異常遇八。
其中
.compose(MainActivity.this.<HttpResponseResult<List<String>>>bindToLifecycle())
是與當前的 Activity 進行綁定矛绘,Activity 需要繼承 RxAppCompatActivity 或者 RxActivity ,如果已有自己的 BaseActivity,則讓 BaseActivity 去繼承即可刃永。Fragment類似货矮。
.compose(TransformerHelper.<List<String>>transformer())
是對請求結果進行處理,即從 HttpResponseResult
取出 T
斯够。
.compose(new DialogTransformer(MainActivity.this).<List<String>>showDialog())
是操作 ProgressDialog 的囚玫,其生命周期會伴隨整個請求,不需要時可以不加读规。
一般在請求成功后會進行數據處理抓督,而失敗時則進行 Toast 提示用戶,CommonObserver
中已經對錯誤進行了處理束亏,自動彈出 Toast铃在,如果不需要彈出 Toast ,重寫 CommonObserver
的 onFailed(HttpResponseException responseException)
方法即可。如果需要針對不同的業(yè)務邏輯錯誤進行不同的處理定铜,則使用 responseException.getStatus()
得到錯誤碼進行處理即可阳液。
非 Restful 接口
由于非 Restful 接口用的可能比較少,所以沒對其進行整理揣炕,只提供了一個實現帘皿,當然,如果項目中非 Restful 接口用的比較多的話還是封裝一下比較好畸陡。
ServiceManager
.getApiService()
.testGet1()
.compose(SchedulerTransformer.<String>transformer())//線程轉換
.compose(MainActivity.this.<String>bindToLifecycle())//綁定生命周期鹰溜,防止內存泄露
.compose(new DialogTransformer(MainActivity.this).<String>transformer())//progressDialog
.subscribe(new Observer<String>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(String s) {
Logger.e(s);
}
@Override
public void onError(Throwable e) {
Logger.e(e.toString());
}
@Override
public void onComplete() {
}
});
下載操作
final DownloadHelper downloadHelper = new DownloadHelper(url, dirPath, fileName);
downloadHelper.downloadFile(new DownloadListener() {
@Override
public void update(long bytesRead, long contentLength) {
Logger.e("----bytesRead=" + bytesRead);
Logger.e("----contentLength=" + contentLength);
progressDialog.setProgress((int) ((100 * bytesRead) / contentLength));
}
@Override
public void onSuccess(File file) {
progressDialog.cancel();
Logger.e(file.getAbsolutePath() + "----" + file.length());
}
@Override
public void onFailure(Throwable t) {
progressDialog.cancel();
Logger.e("----" + t.toString());
}
});
取消下載
downloadHelper.cancelDownload();