RxJava和Retrofit - 根据服务器响应提升自定义异常

Nim*_*a G 5 android rx-java retrofit

我希望Retrofit根据服务器响应提出自定义异常.例如,在以下结构中:

{
"code":0,
"message":"OK",
"data":{....}
}
Run Code Online (Sandbox Code Playgroud)

如果code不是0,我想为订阅者引发一个例外.如何使用Retrofit和Rx?我更喜欢只编写一次这个逻辑并将其应用于改造返回的所有可观察对象.

Vla*_*nov 7

如果代码不是0,我想为订阅者引发一个例外.如何使用Retrofit和Rx?

您可以使用Observable.flatMap运营商:

api.request().flatMap(response -> {
    if (response.getCode() != 0) {
        return Observable.error(new Exception("Remote error occurred"));
    }

    return Observable.just(response);
});
Run Code Online (Sandbox Code Playgroud)

我更喜欢只编写一次这个逻辑并将其应用于改造返回的所有可观察对象.

不幸的是,没有办法使用retrofitrx-java.您必须为每次retrofit通话编写上面的代码.您唯一能做的就是使用Observable.compose方法并减少实际必须编写的样板量.

api.request().compose(new ResponseTransformer<Response>());
Run Code Online (Sandbox Code Playgroud)

这是ResponseTransformer班级:

public static class ResponseTransformer<T extends Response> implements Observable.Transformer<T, T> {
    @Override
    public Observable<T> call(final Observable<T> observable) {
        return observable.flatMap(response -> {
            if (response.getCode() != 0) {
                return Observable.error(new Exception("Remote error occurred"));
            }

            return Observable.just(response);
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

UPDATE

好吧,正如我所说,没有办法避免仅使用retrofit和使用样板代码rxjava,但您可以使用动态代理解决它(请注意,您不需要再调用compose):

final Api api = restAdapter.create(Api.class);

final ClassLoader loader = api.getClass().getClassLoader();
final Class<?>[] interfaces = api.getClass().getInterfaces();

final Api proxy = (Api) Proxy.newProxyInstance(loader, interfaces, new ResponseInvocationHandler(api));

proxy.request().subscribe(response -> {
    System.out.println("Success!");
});
Run Code Online (Sandbox Code Playgroud)

ResponseInvocationHandler 类:

public static class ResponseInvocationHandler implements InvocationHandler {
    private final Object target;

    public ResponseInvocationHandler(final Object target) {
        this.target = target;
    }

    @Override
    @SuppressWarnings({"unchecked"})
    public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
        final Object result = method.invoke(target, args);

        if (result instanceof Observable) {
            return Observable.class.cast(result).compose(new ResponseTransformer<>());
        }

        return result;
    }
}
Run Code Online (Sandbox Code Playgroud)