根据 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时表示业务处理成功,数据正确。反之业务处理有误,用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)
方法即可。如果需要针对不同的业务逻辑错误进行不同的处理,则使用 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();