使用RxJava + Retrofit失败时返回自定义异常

Lui*_*uiz 3 android rx-java retrofit2

我有一个必须返回的存储库类:Observable<List<SomeObject>我这样做:

 @Override
    public Observable<List<SomeObject>> getAllById(Long id) {
        if (!AndroidUtils.isNetworkAvailable(mContext))
            return Observable.error(new NoNetworkConnectionException());

        return mRestService.get(id);
    }
Run Code Online (Sandbox Code Playgroud)

这种方法正常工作,问题是我想在发生故障时返回自定义异常,但我不知道使用rxjava执行此操作的最佳方法.

到目前为止,唯一有效的解决方案是这样的:

@Override
public Observable<List<SomeObject>> getAllById(Long id) {
    if (!AndroidUtils.isNetworkAvailable(mContext))
        return Observable.error(new NoNetworkConnectionException());

    return Observable.create(subscriber -> {
        mRestService.get(id).subscribe(new Observer<List<SomeObject>>() {
            @Override
            public void onCompleted() {
                subscriber.onCompleted();
            }

            @Override
            public void onError(Throwable e) {
                if (e instanceof HttpException  && ((HttpException) e).code() == 401)
                    subscriber.onError(new UnathorizedException());
                else
                    subscriber.onError(e);
            }

            @Override
            public void onNext(List<SomeObject> objects) {
                subscriber.onNext(objects);
            }
        });
    });
}
Run Code Online (Sandbox Code Playgroud)

我知道使用Observable.create不是一件好事,但我无法想出另一种方法.

RestService是这样的:

public interface RestService {

    @GET("objects/{id}")
    Observable<List<SomeObject>> get(@Path("id") Long id);
}
Run Code Online (Sandbox Code Playgroud)

如果有人知道更好的方法,请告诉我.

谢谢!

dwu*_*sen 11

您可以使用运算符onErrorResumeNext将异常映射到另一个异常.

mRestService.get(id)
            .onErrorResumeNext(e -> {
                if (e instanceof HttpException  && ((HttpException) e).code() == 401)
                    return Observable.error(new UnathorizedException());
                else
                    return Observable.error(e);
            })
            .subscribe();
Run Code Online (Sandbox Code Playgroud)


m.o*_*hov 0

您可以尝试以下操作:

    RestService restService = Mockito.mock(RestService.class);

    Observable<List<Object>> networkExOrEmpty = isNetworkAvailable() ?
            Observable.empty() :
            Observable.error(new NoNetworkConnectionException());

    Observable<List<Object>> resultOrEx = restService
            .getAllById(42L)
            .materialize()
            .map(res -> {
                if (res.isOnError()) {
                    Throwable err = res.getThrowable();
                    if (err instanceof HttpException && ((HttpException) err).code() == 401) {
                        return Notification.createOnError(new UnauthrizedException());
                    } else {
                        return Notification.createOnError(err);
                    }
                } else {
                    return res;
                }
            }).dematerialize();


    Observable<List<Object>> result = networkExOrEmpty.concatWith(resultOrEx);
Run Code Online (Sandbox Code Playgroud)

首先Observable根据网络连接状态发出错误或不发出任何信号,然后将其与Retrofit服务结果连接起来。Observable.materialize()允许对错误项采取行动:将适当的异常推送到下游,并按原样传递非错误通知。