RxJava2 + Retrofit2 处理data为null的情况

版权声明:本文为博主原创文章,未经博主允许不得转载。 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还是会报异常的

猜你喜欢

转载自blog.csdn.net/ZuoZuoShengHen/article/details/84981055