版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/ZuoZuoShengHen/article/details/84981055
最近项目中使用了RxJava2+ Retrofit2框架,框架基本都是统一封装HttpBean,使用map操作符转化数据,然后根据code码的逻辑去处理业务,开发过程中遇到一个问题,服务器返回的json数据格式为{"code": 200, "data": null, "message": null}, 发现客户端竟然报错解析不了。。。
附上之前写的代码:
public class RxFunction<T> implements Function<BaseHttpBean<T>, T> {
@Override
public T apply(BaseHttpBean<T> httpBean) throws Exception {
String resultCode = httpBean.getCode();
if (!HttpCode.SUCCESS.equals(resultCode)) {
throw new ApiException(resultCode, httpBean.getMessage());
}
return httpBean.getData();
}
}
网上百度了一下是说RxJava2之后map操作符就不允许发送一个null从上游交给下游了。那可怎么办哪,那时候天真的以为不要让服务器返回data为null的数据就好了,搞得后台的人一脸懵逼~ 哈哈 。
最后从这篇文章里借鉴了思路,解决了问题。https://www.jianshu.com/p/f1957c9c2240
首先新写一个类:Optional, 这个是Java8新出的特性。是为了解决null安全问题出的API(核心)
public class Optional<M> {
private final M optional; // 接收到的返回结果
public Optional(@Nullable M optional) {
this.optional = optional;
}
// 判断返回结果是否为null
public boolean isEmpty() {
return this.optional == null;
}
// 获取不能为null的返回结果,如果为null,直接抛异常,经过二次封装之后,这个异常最终可以在走向RxJava的onError()
public M get() {
if (optional == null) {
throw new NoSuchElementException("No value present");
}
return optional;
}
// 获取可以为null的返回结果
public M getIncludeNull() {
return optional;
}
}
接下来把泛型T使用Optinal包装一下。
public class RxTransformer {
public static <T> ObservableTransformer<BaseHttpBean<T>, Optional<T>> handle_result() {
return upstream -> upstream
.flatMap(new Function<BaseHttpBean<T>, ObservableSource<Optional<T>>>() {
@Override
public ObservableSource<Optional<T>> apply(@NonNull BaseHttpBean<T> result) throws Exception {
if (HttpCode.SUCCESS.equals(result.getCode())) {
// result.transform() 就是将返回结果进行包装
return createHttpData(result.transform());
} else {
// 发送请求失败的信息
return Observable.error(new ApiException(result.getCode(), result.getMessage()));
}
return Observable.empty();
}
}
);
}
public static <T> Observable<Optional<T>> createHttpData(Optional<T> t) {
return Observable.create(e -> {
try {
e.onNext(t);
e.onComplete();
} catch (Exception exc) {
e.onError(exc);
}
});
}
}
原来的结构如下:
public Observable<LoginBean> login(Map map) {
return Api.getApiService()
.requestLogin(getRequestBody(map))
.map(new RxFunction<LoginBean>())
.compose(RxSchedulers.io2Main());
}
修改之后的结构如下:
public Observable<Optional<LoginBean>> login(Map<String, Object> map) {
return Api.getApiService()
.requestLogin(map)
.compose(RxTransformer.handle_result())
.compose(RxSchedulers.io2Main());
}
最后接收T的时候只需要取getIncludeNull()即可。注意是取getIncludeNull ,取get还是会报异常的