RetroHttp(四) — 实现串联请求
前言
RetroHttp
作为一个基于Retrofit2.x
网络请求的封装库,致力于简洁快速的实现网络通讯,在之前的文章里,我已经对RetroHttp
的使用做了些相关介绍,大家感兴趣的话可以参考以下文章:
RetroHttp(一) — 下载使用介绍
RetroHttp(二) — 下载支持增量更新
RetroHttp(三) — kotlin版网络请求
在Android
网络请求过程中,我们有时会遇到请求串联的情况。即第一个请求发起成功后,才能发起第二个请求。那么今天就让我们来了解下RetroHttp
基于串联请求的使用吧。
今天涉及知识有:
- 串联请求业务逻辑
- 串联请求帮助类ObservableHelper方法简介
- 串联请求的使用示例
- 需要注意的事项
一. 串联请求业务逻辑
在开发过程中,有时我们回遇到串联请求
的情况,如发起注册通讯成功后,立马发起登录的通讯。他们的逻辑特点是,第一个通讯成功后,才发起第二个通讯,当第一个通讯发送失败后,则终止发起后续通讯。这里我将此种通讯逻辑称为串联请求
二.串联请求帮助类ObservableHelper方法简介
RetroHttp
库中也支持串联请求
,其功能封装到帮助类ObservableHelper
中。下面就来看看
ObservableHelper
中关于串联请求的方法吧:
/***
* 接连发起多个通讯的Observable(一个接一个,但顺序不确定)
*
* @param observable
* @param function Function<T,R>: T->进入该方法的参数, R->输出结果
* @param <T>
* @return
*/
public static <T>Observable getNextObservable(Observable<T>observable, Function<T, ObservableSource<T>> function)
/***
* 按顺序发起通讯的Observable(一个接一个,且按顺序发送)
*
* @param observable
* @param function Function<T,R>: T->进入该方法的参数, R->输出结果
* @param <T>
* @return
*/
public static <T> Observable getNextObservableInOrder(Observable<T>observable, Function<T, ObservableSource<T>> function)
ObservableHelper
类支持发起无序
和有序
的串联请求
,主要如下:
- getNextObservable: 支持发起
无序串联请求
- getNextObservableInOrder: 支持发起
有序串联请求
无序串联请求
即依次发起A
,B
,C
三个网络请求,但三个请求返回结果的顺序未知。有序串联请求
即依次发起A
,B
,C
三个网络请求,返回结果的顺序也为A
,B
,C
。
三.串联请求的使用示例
下面以有序串联请求
为例,给出其在Presenter
中发起网络请求的核心代码:
3.1 Java 版
public void checkVersion() {
ApiService apiService = (ApiService) ApiRetrofitor.getInstance().getBaseRetrofitor().getApiService();
//发起第一个请求
Observable observable = apiService.checkVersion();
observable = ObservableHelper.getNextObservableInOrder(observable, new Function<ResponseData, ObservableSource<ResponseData>>() {
@Override
public ObservableSource<ResponseData> apply(ResponseData responseData) throws Exception{
LogUtil.i("=======Function执行apply======");
//解析第一个通讯的结果
int code = responseData.getCode();
//只有在第一此通讯顺利的时候,才发起第二次通讯
if (code == ResponseCode.SUCCES_CODE) {//成功
LogUtil.i("=======准备发起第二次通讯======");
//准备发起第二次通讯
RequestUser user = new RequestUser();
user.setUsername("xxxx");
user.setPassword("xxxxxx");
return apiService.login(user);
}
return null;
}
});
// //按顺序发起第三个通讯
// observable = ObservableHelper.getNextObservableInOrder(observable, new Function<> ...)
//加载loading
LoadingDialog.getInstance().showLoading(mContext);
//处理最后一次通讯的结果
RxManager.connect(observable, new ApiObserver<ResponseData>() {
@Override
public void doNext(ResponseData responseData) {
LoadingDialog.getInstance().hideLoading();
int code = responseData.getCode();
String message = responseData.getMessage();
if (code == ResponseCode.SUCCES_CODE) {//成功
Object object=responseData.getData();
if(object!=null){
String temp= GsonUtil.gsonString(object);
User user= GsonUtil.gsonToBean(temp,User.class);
mView.loginSuccess(user);
}else{
mView.loginFail("获取信息为空");
}
} else {
mView.loginFail(message);
}
}
@Override
public void doError(ServerException e) {
LoadingDialog.getInstance().hideLoading();
LogUtil.i("=====error====="+e.getMessage());
mView.loginFail("发生错误");
}
});
}
3.2 Kotlin版
fun checkVersion() {
var apiService =ApiRetrofitor.getBaseRetrofitor<BaseRetrofitor>().apiService as ApiService
//发起第一个请求
var observable: Observable<ResponseData<Any>> = apiService.checkVersion()
observable = ObservableHelper.getNextObservableInOrder(
observable,object : Function<ResponseData, ObservableSource<ResponseData>>() {
@Throws(Exception::class)
fun apply(responseData: ResponseData): ObservableSource<ResponseData>? {
LogUtil.i("=======Function执行apply======")
//解析第一个通讯的结果
var code = responseData.code
//只有在第一此通讯顺利的时候,才发起第二次通讯
if (code == ResponseCode.SUCCES_CODE) {//成功
LogUtil.i("=======准备发起第二次通讯======")
//准备发起第二次通讯
var user = RequestUser()
user.setUsername("xxxx")
user.setPassword("xxxxxx")
return apiService.login(user)
}
return null
}
})
// //按顺序发起第三个通讯
// observable = ObservableHelper.getNextObservableInOrder(observable, new Function<> ...)
//加载loading
LoadingDialog.getInstance().showLoading(mContext)
//处理最后一次通讯的结果
RxManager.connect(observable, object : ApiObserver<ResponseData>() {
fun doNext(responseData: ResponseData) {
LoadingDialog.getInstance().hideLoading()
var code = responseData.code
var message = responseData.message
if (code == ResponseCode.SUCCES_CODE) {//成功
var obj = responseData.data
if (obj != null) {
var temp = GsonUtil.gsonString(obj)
var user = GsonUtil.gsonToBean(temp, User::class.java)
mView.loginSuccess(user)
} else {
mView.loginFail("获取信息为空")
}
} else {
mView.loginFail(message)
}
}
fun doError(e: ServerException) {
LoadingDialog.getInstance().hideLoading()
LogUtil.i("=====error=====" + e.message)
mView.loginFail("发生错误")
}
})
}
四.需要注意的事项
这里需要注意的是,以上面依次发起的两个请求为例,checkVersion()
发起的请求在第一个getNextObservableInOrder
中接收并处理,然后在该方法的apply(T t)
方法中一般只处理第一个同通讯获取成功的情况,处理OK后接着在此方法中发起第二个请求。若第一个通讯失败,则失败的处理会有结尾的RxManager.connect(...)
来处理。若还想发起第三个请求,则像上面代码一样,在后面接着写observable = ObservableHelper.getNextObservableInOrder(observable, new Function<> ...)
,然后在此方法中处理第二个请求的接收值,处理完后,发起第三个请求...
最后用RxManager.connect(...)
来处理最后一个请求的返回值。值得注意的是,在RxManager.connect(...)
的doError(ServerException e)
中将处理所有请求的异常处理。由于串联请求
的特点,会导致doError(ServerException e)
无法判断处理的是哪一个通讯的异常,故在开发过程中,我们只会在doError(ServerException e)
中提供针对最后一次通讯的模糊提示。