Android RxJava+;改装->;用于集中响应处理的API调用的BaseObservable

Android RxJava+;改装->;用于集中响应处理的API调用的BaseObservable,android,rx-java,retrofit2,rx-android,Android,Rx Java,Retrofit2,Rx Android,我是RxJava新手,所以如果这听起来太生疏,请原谅我:-) 到目前为止,我有一个抽象的Callback类,它实现了Retofit回调。在那里,我捕获回调的“onResponse”和“onError”方法,并在最终转发到自定义实现的方法之前处理各种错误类型。 我还使用这个集中式类来记录请求/响应应用程序日志和其他内容 例如:对于来自服务器的特定错误代码,我在响应正文中收到一个新的身份验证令牌,刷新该令牌,然后克隆。将调用排入队列。 当然,对于来自我的服务器的响应,还有其他几个全局行为 当前解决方

我是RxJava新手,所以如果这听起来太生疏,请原谅我:-)

到目前为止,我有一个抽象的Callback类,它实现了Retofit回调。在那里,我捕获回调的“onResponse”和“onError”方法,并在最终转发到自定义实现的方法之前处理各种错误类型。 我还使用这个集中式类来记录请求/响应应用程序日志和其他内容

例如:对于来自服务器的特定错误代码,我在响应正文中收到一个新的身份验证令牌,刷新该令牌,然后克隆。将调用排入队列。 当然,对于来自我的服务器的响应,还有其他几个全局行为

当前解决方案(无Rx):

公共抽象void onResponse(Call-Call、Response-Response、boolean-issucess);
公共抽象void onFailure(调用、响应、可丢弃的t、布尔isTimeout);
@凌驾
公共void onResponse(调用、响应){
如果(取消)返回;
if(response!=null&&!response.issusccessful()){
if(response.code()=“SomeCode”&&retryCount
我的问题是:在最终链接(或重试)到订阅者方法之前,是否有任何方法可以实现这种集中式响应处理行为

我发现这两个链接都有一个很好的起点,但不是一个具体的解决方案。任何帮助都将不胜感激


< P>您是否考虑过使用RXJava适配器进行改装? 在你的gradle文件中添加

compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'
这是一个改造界面

public interface Service {
@GET("userauth/login?")
Observable<LoginResponse> getLogin(
        @Query("v") String version,
        @Query("username") String username,
        @Query("password") String password);
}
公共接口服务{
@获取(“userauth/login?”)
可观察的getLogin(
@查询(“v”)字符串版本,
@查询(“用户名”)字符串用户名,
@查询(“密码”)字符串(密码);
}
这是我的实现

Service.getLogin(
            VERSION,
            "username",
            "password")
            .subscribe(new Subscriber<LoginResponse>() {
                @Override
                public void onCompleted() {

                }

                @Override
                public void onError(Throwable e) {

                }

                @Override
                public void onNext(LoginResponse loginResponse) {

                }
            });
Service.getLogin(
版本
“用户名”,
“密码”)
.subscribe(新订户(){
@凌驾
未完成的公共无效(){
}
@凌驾
公共无效申报人(可丢弃的e){
}
@凌驾
public void onNext(登录回复登录回复){
}
});

请注意,我正在使用gson转换器工厂来解析我的响应,因此返回了一个pojo(普通Ole Java对象)。

您提供的两个链接是一个非常好的起点,我使用它们来构建解决方案以应对意外事件

  • 网络错误有时是由于暂时缺少网络连接或切换到低吞吐量网络标准(如EDGE)而发生的,这会导致SocketTimeoutException
  • 服务器错误->有时由于服务器过载而发生
我已重写
CallAdapter.Factory
,以处理错误并对其作出适当反应

  • 从找到的文件导入
    RetryWithDelayIf

  • 覆盖CallAdapter.Factory以处理错误:

    public class RxCallAdapterFactoryWithErrorHandling extends CallAdapter.Factory {
        private final RxJavaCallAdapterFactory original;
    
        public RxCallAdapterFactoryWithErrorHandling() {
            original = RxJavaCallAdapterFactory.create();
        }
    
        @Override
        public CallAdapter<?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
            return new RxCallAdapterWrapper(retrofit, original.get(returnType, annotations, retrofit));
        }
    
        public class RxCallAdapterWrapper implements CallAdapter<Observable<?>> {
            private final Retrofit retrofit;
            private final CallAdapter<?> wrapped;
    
            public RxCallAdapterWrapper(Retrofit retrofit, CallAdapter<?> wrapped) {
                this.retrofit = retrofit;
                this.wrapped = wrapped;
            }
    
            @Override
            public Type responseType() {
                return wrapped.responseType();
            }
    
            @SuppressWarnings("unchecked")
            @Override
            public <R> Observable<?> adapt(final Call<R> call) {
                return ((Observable) wrapped.adapt(call)).onErrorResumeNext(new Func1<Throwable, Observable>() {
                    @Override
                    public Observable call(Throwable throwable) {
                        Throwable returnThrowable = throwable;
                        if (throwable instanceof HttpException) {
                            HttpException httpException = (HttpException) throwable;
                            returnThrowable = httpException;
                            int responseCode = httpException.response().code();
                            if (NetworkUtils.isClientError(responseCode)) {
                                returnThrowable = new HttpClientException(throwable);
                            }
                            if (NetworkUtils.isServerError(responseCode)) {
                                returnThrowable = new HttpServerException(throwable);
                            }
                        }
    
                        if (throwable instanceof UnknownHostException) {
                            returnThrowable = throwable;
                        }
    
                        return Observable.error(returnThrowable);
                    }
                }).retryWhen(new RetryWithDelayIf(3, DateUtils.SECOND_IN_MILLIS, new Func1<Throwable, Boolean>() {
                    @Override
                    public Boolean call(Throwable throwable) {
                        return throwable instanceof HttpServerException
                                || throwable instanceof SocketTimeoutException
                                || throwable instanceof UnknownHostException;
                    }
                }));
            }
        }
    }
    
  • Extra:如果您希望解析来自API的错误(不调用
    UnknownHostException
    HttpException
    MalformedJsonException
    等的错误),则需要在构建
    改型
    实例期间重写并使用自定义错误。解析响应并检查它是否包含错误。如果是,则抛出错误,错误将在上述方法中处理。

    查看如何处理。 这里是api调用和传递请求模型和响应模型

    public interface RestService {
    //SEARCH_USER
    @POST(SEARCH_USER_API_LINK)
    Observable<SearchUserResponse> getSearchUser(@Body SearchUserRequest getSearchUserRequest);
    }
    
    这是api调用,在活动中调用它

    @Inject
    Scheduler mMainThread;
    @Inject
    Scheduler mNewThread;
    
     //getSearchUser api method
    public void getSearchUser(String user_id, String username) {
    
        SearchUserRequest searchUserRequest = new SearchUserRequest(user_id, username);
    
        mObjectRestService.getSearchUser(searchUserRequest).
                subscribeOn(mNewThread).
                observeOn(mMainThread).
                subscribe(searchUserResponse -> {
                    Timber.e("searchUserResponse :" + searchUserResponse.getResponse().getResult());
                    if (isViewAttached()) {
                        getMvpView().hideProgress();
                        if (searchUserResponse.getResponse().getResult() == ApiConstants.STATUS_SUCCESS) {
    
                        } else {
    
                        }
                    }
                }, throwable -> {
                    if (isViewAttached()) {
    
                    }
                });
    }
    

    希望这能对您有所帮助。

    当然,我说的是使用RxJava适配器。您的示例是改装+Rx的最基本用途。问题是如何在不使用Rx的情况下获得示例中使用的模式,以便在使用RxCalAdapter时进行通用和集中的错误处理。谢谢您的回答。我将尝试实现此代码,并在接受答案之前通知您。只是一个问题。。。对于您的解决方案,您的退货类型是什么?可观察的,可观察的或仅仅是普通的可观察的。详细说明你的“额外”也很好(;
    Observable
    的类型在有代码或没有代码的情况下保持不变。如果请求重复,或者抛出比默认改型错误更具体的错误,那么它只是延迟响应:
    HttpException
    。请提供一个处理Api错误的代码片段,该错误不会像您的mentio那样调用UnknownHostException在您的“额外”中添加了ned?提前感谢。是否有可能使解决方案与rxjava2和新发布的改型rxjava2呼叫适配器兼容?
    public interface RestService {
    //SEARCH_USER
    @POST(SEARCH_USER_API_LINK)
    Observable<SearchUserResponse> getSearchUser(@Body SearchUserRequest getSearchUserRequest);
    }
    
    public RestService getRestService() {
    
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(ApiConstants.BASE_URL)
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .client(getOkHttpClient())
                .build();
    
        return retrofit.create(RestService.class);
    }
    
    //get OkHttp instance
    @Singleton
    @Provides
    public OkHttpClient getOkHttpClient() {
    
        HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
        httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
    
        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        builder.interceptors().add(httpLoggingInterceptor);
        builder.readTimeout(60, TimeUnit.SECONDS);
        builder.connectTimeout(60, TimeUnit.SECONDS);
        return builder.build();
    }
    
    @Inject
    Scheduler mMainThread;
    @Inject
    Scheduler mNewThread;
    
     //getSearchUser api method
    public void getSearchUser(String user_id, String username) {
    
        SearchUserRequest searchUserRequest = new SearchUserRequest(user_id, username);
    
        mObjectRestService.getSearchUser(searchUserRequest).
                subscribeOn(mNewThread).
                observeOn(mMainThread).
                subscribe(searchUserResponse -> {
                    Timber.e("searchUserResponse :" + searchUserResponse.getResponse().getResult());
                    if (isViewAttached()) {
                        getMvpView().hideProgress();
                        if (searchUserResponse.getResponse().getResult() == ApiConstants.STATUS_SUCCESS) {
    
                        } else {
    
                        }
                    }
                }, throwable -> {
                    if (isViewAttached()) {
    
                    }
                });
    }