Tôi muốn nêu ngoại lệ cho người đăng ký nếu mã là bất kỳ điều gì khác ngoài 0. Làm thế nào để sử dụng Retrofit và Rx?
Bạn có thể sử dụng một nhà điều hành Observable.flatMap
:
api.request().flatMap(response -> {
if (response.getCode() != 0) {
return Observable.error(new Exception("Remote error occurred"));
}
return Observable.just(response);
});
Tôi rất muốn viết logic này chỉ một lần và có nó áp dụng cho tất cả các quan sát được trả về bởi retrofit.
Thật không may, không có cách nào để thực hiện việc đó bằng cách sử dụng retrofit
và rx-java
. Bạn có để viết mã ở trên cho mỗi cuộc gọi retrofit
. Điều duy nhất bạn có thể làm là sử dụng phương pháp Observable.compose
và giảm số lượng bản mẫu mà bạn thực sự phải viết.
api.request().compose(new ResponseTransformer<Response>());
Và đây là lớp 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);
});
}
}
CẬP NHẬT
Vâng, như tôi đã nói, không có cách nào để tránh mã boilerplate chỉ sử dụng retrofit
và rxjava
, nhưng bạn có thể giải quyết vấn đề này với dynamic proxies (lưu ý rằng bạn không cần phải gọi compose
nữa):
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!");
});
ResponseInvocationHandler
lớp:
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;
}
}
Cảm ơn, rất hữu ích – Nima
@Nima kiểm tra câu trả lời của tôi cập nhật, nó có thể thậm chí còn hữu ích hơn. –