我有一个必须返回的存储库类:Observable<List<SomeObject>
,
我这样做:
@Override
public Observable<List<SomeObject>> getAllById(Long id) {
if (!AndroidUtils.isNetworkAvailable(mContext))
return Observable.error(new NoNetworkConnectionException());
return mRestService.get(id);
}
这种方法正常,问题是我想返回自定义异常 如果出现故障,但我不知道使用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);
}
});
});
}
我知道使用Observable.create不是一件好事,但我无法弄明白 另一种方法。
RestService就是这样:
public interface RestService {
@GET("objects/{id}")
Observable<List<SomeObject>> get(@Path("id") Long id);
}
如果有人知道更好的方法,请告诉我。
谢谢!
答案 0 :(得分:9)
您可以使用运算符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();
答案 1 :(得分:1)
我在项目中通过在创建休息服务时添加拦截器来完成此操作。这样就可以在请求到达您的休息服务之前检查错误。
OkHttpClient.Builder httpClientBuilder = new OkHttpClient.Builder();
httpClientBuilder.addInterceptor(new ErrorInterceptor());
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(myBaseUrl)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.client(httpClientBuilder.build())
.build();
ErrorInterceptor类看起来像
public class ErrorInterceptor implements Interceptor {
private static final Charset UTF8 = Charset.forName("UTF-8");
@Override
public Response intercept(Chain chain) throws IOException {
Request originalRequest = chain.request();
Response response = chain.proceed(originalRequest);
if (response.code() >= 400) {
throwError(response);
return response;
} else {
return response;
}
}
private void throwError (Response response) throws IOException {
ResponseBody responseBody = response.body();
BufferedSource source = responseBody.source();
source.request(Long.MAX_VALUE); // Buffer the entire body.
Buffer buffer = source.buffer();
Charset charset = UTF8;
MediaType contentType = responseBody.contentType();
if (contentType != null) {
charset = contentType.charset(UTF8);
}
if (responseBody.contentLength() != 0) {
String responseJSON = buffer.clone().readString(charset);
Gson gson = new Gson();
Type type = new TypeToken<ErrorResponse>() {}.getType();
ErrorResponse error = null;
try {
error = gson.fromJson(responseJSON, type);
}
catch (Exception e) {
int a = 1;
}
if (error != null && error.hasErrors())
throw ErrorMapper.mapError(error.getFirstError());
}
}
}
我的ErrorResponse类
public class ErrorResponse {
private List<Error> errors;
public boolean hasErrors () {
return errors != null && errors.size() > 0;
}
public Error getFirstError() {
if (errors == null || errors.size() == 0) return null;
return errors.get(0);
}
}
在我的ErrorMapper中,我只是根据来自服务器的一组可能消息检查错误消息,并创建一个包含要在客户端上显示的消息的新错误。
我只是在这里查看第一个错误,但您应该可以轻松地将其用于多个错误。
答案 2 :(得分: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);
从Observable
开始,它发出错误或什么也不发送,具体取决于网络连接状态,然后将其与Retrofit
服务的结果连接起来。 Observable.materialize()
允许用户对错误项执行操作:向下游推送相应的异常,并按原样传递非错误通知。