RxJava + Retrofit -> BaseObservable 用于 API 调用以进行集中响应处理

2024-02-16

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

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

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

当前解决方案(无 Rx):

    public abstract void onResponse(Call<T> call, Response<T> response, boolean isSuccess);

    public abstract void onFailure(Call<T> call, Response<T> response, Throwable t, boolean isTimeout);

    @Override
    public void onResponse(Call<T> call, Response<T> response) {
        if (_isCanceled) return;

        if (response != null && !response.isSuccessful()) {
            if (response.code() == "SomeCode" && retryCount < RETRY_LIMIT) {
                TokenResponseModel newToken = null;
                try {
                    newToken = new Gson().fromJson(new String(response.errorBody().bytes(), "UTF-8"), TokenResponseModel.class);
                } catch (Exception e) {
                    e.printStackTrace();
                }

                    SomeClass.token = newToken.token;
                    retryCount++;
                    call.clone().enqueue(this);
                    return;
                }
            }
        } else {
            onResponse(call, response, true);
            removeFinishedRequest();
            return;
        }

        onFailure(call, response, null, false);
        removeFinishedRequest();
    }

    @Override
    public void onFailure(Call<T> call, Throwable t) {
        if (_isCanceled) return;

        if (t instanceof UnknownHostException)
            if (eventBus != null)
                eventBus.post(new NoConnectionErrorEvent());

        onFailure(call, null, t, false);
        removeFinishedRequest();
    }

我的问题是:在最终链接(或重试)回订阅者方法之前,有什么方法可以实现这种集中式响应处理行为?

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

RxJava 中自定义 API 异常后强制请求重试 https://stackoverflow.com/questions/26919190/forcing-request-retry-after-custom-api-exceptions-in-rxjava?rq=1

Retrofit 2 和 RxJava 错误处理运算符 https://stackoverflow.com/questions/33740066/retrofit-2-and-rxjava-error-handling-operators


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

  • 有时会由于暂时缺少网络连接或切换到低吞吐量网络标准(例如 EDGE)而发生网络错误,这会导致 SocketTimeoutException
  • 服务器错误 -> 有时由于服务器过载而发生

我已经覆盖了CallAdapter.Factory处理错误并对错误做出适当反应。

  1. Import RetryWithDelayIf来自solution https://stackoverflow.com/a/33768184/6507689你发现了

  2. 覆盖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;
                    }
                }));
            }
        }
    }
    

    HttpServerException只是一个自定义异常。

  3. 使用它在Retrofit.Builder https://square.github.io/retrofit/2.x/retrofit/retrofit2/Retrofit.Builder.html

    Retrofit retrofit = new Retrofit.Builder()
            .addCallAdapterFactory(new RxCallAdapterFactoryWithErrorHandling())
            .build();
    

Extra:如果你想解析来自API的错误(不调用的错误UnknownHostException, HttpException or MalformedJsonException或等等)你需要覆盖Factory https://square.github.io/retrofit/2.x/retrofit/retrofit2/Converter.Factory.html并在构建过程中使用自定义的Retrofit实例。解析响应并检查它是否包含错误。如果是,则抛出错误,错误将在上面的方法内处理。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

RxJava + Retrofit -> BaseObservable 用于 API 调用以进行集中响应处理 的相关文章

  • 未为模块“Example-Example”指定 APK 路径

    我是 Android 应用程序开发领域的新手 我正在创建一个项目示例安卓工作室 我有我的午餐列表 java文件输入src main java apt tutorial lunchlist 直到昨天一切都工作正常 但是当我今天打开 andro
  • 我所有的布局 xml 文件都变成了自动生成的文件

    昨天我的应用程序上的所有内容都运行完美 但今天当我打开 Android Studio 时 所有 xml 文件都已损坏 不确定这是否是正确的术语 每个人都是这样的 我今天遇到了同样的问题 下面是我所做的几个步骤 我取得了成功来解决这个问题 只
  • Mono for Android,读取和写入 XLSX

    我正在使用 Mono for Android 开发一个应用程序 我需要读取和创建 XLSX Excel 文件的功能 我尝试过EPPlus和NPOI 并快速浏览了一下微软的Open XML SDK 发现了以下问题 EPPlus 需要 Wind
  • 方法调用 mActionBar=getActionBar() 给出错误[关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我正在使用支持库android support v7 app actionbar因为我想要操作栏API 级别 8以上 但是下面的句子给了我
  • React Native 检查平板电脑或屏幕是否以英寸为单位

    我为平板电脑和移动设备建立了不同的渲染逻辑 我想知道是否有办法获取屏幕尺寸 以英寸为单位 或者甚至可能是任何模块自动检测设备是否是平板电脑 我没有直接使用尺寸 API 来获取屏幕分辨率的原因是 许多 Android 平板电脑的分辨率低于许多
  • 如何使用 SyncAdapter 处理远程服务器的 RESTful 更新

    我观看了 Google I O REST 演讲并阅读了幻灯片 http www google com events io 2010 sessions developing RESTful android apps html http www
  • Flutter - 每次应用程序重新启动后保留变量的值

    在我的一页上 我希望我的用户从一个变量上的默认文本开始 codeDialog 然后我希望他们更改该文本 之后他们编写的文本将成为我的新默认文本 遗憾的是我无法让它发挥作用 现在 当我重新启动应用程序并打开该屏幕时 它会重置为null 我认为
  • 如何让Service即使被系统杀死也无法删除?

    我正在创建一个蓝光过滤器应用程序 因此 我想显示所有应用程序的视图 我通过以下服务做到了 public class OverlayService extends Service public OverlayService View mVie
  • 指标元素之间的空间

    如何增加 减少指标元素之间的空间ViewPagerIndicator 我用过CirclePageIndicator 我能够通过以下步骤在两个指标之间留出更多空间 打开源代码CirclePageIndicator并找到变量mRadius 在第
  • Android:从 https url 获取响应

    问候 我正在开发一个 Android 应用程序 需要通过 https 打开一个 url 带有 POST 参数 并获取响应 我有一个自签名证书 这让情况更加复杂 我还需要接受cookies 有人知道从哪里开始吗 提前谢谢了 Android 附
  • 如何处理应用程序对 3d party 的依赖

    我当前正在开发的应用程序依赖于第三方应用程序 OIFileManager 我的问题是处理这些依赖关系的一般方法是什么 告诉用户解决它 嵌入 3d party apk 如果其许可证允许 自动解决 也许Android市场有相应的系统 没有自动的
  • 如何在Android应用程序的同一屏幕上显示文本框的值,就像whatsapp一样

    这是我的主文件 我在其中调用按钮上的单击事件来传递值 protected void onCreate Bundle savedInstanceState super onCreate savedInstanceState setConten
  • 如何创建 Google Play 音乐的直接链接?

    据我所知 应用程序的直接链接是 gt market apps collection
  • 拦截来自外部应用程序的意图

    假设我想开发一个以某种方式扩展的应用程序 让我说 合作 非常受欢迎的应用程序我显然无法控制 为了简单起见 我们还假设非常著名的应用程序作者不会发布更新来阻止我的应用程序 我研究了该应用程序的功能并发现它广泛使用BroadcastReceiv
  • AWS MobileHub:重命名 Android / iOS 示例项目

    我是 AWS Mobilehub 的新手 我喜欢它允许我使用 AWS 配置选项创建项目 但是 当我尝试构建应用程序 ios swift android 时 它总是使用我的示例项目作为项目名称 在 AWS 项目的大多数配置设置中 例如使用 c
  • Android - 从服务器获取响应时验证 JSON 以避免 JSONException

    在我的一些与服务器通信并使用 http 获取响应的应用程序中 我使用 json 来格式化数据服务器端 当它到达设备时 我使用类似于我在 stackoverflow 上找到的代码 private class LoadData extends
  • Android 上的 Jetty 上的 Jersey 抛出 ContainerException:“不存在 WebApplication 提供程序”

    我正在尝试在 Android 上的 Jetty 上运行 Jersey 我创建了一个 Android 它使用 Jersey Servlet 实例化 Jetty 服务器 无论如何 当我启动 Jetty 并访问 REST 资源时 在我的例子中 h
  • Android 在通话期间播放音频文件[重复]

    这个问题在这里已经有答案了 对于我的 Android 应用程序 我想在从应用程序接听电话后播放音频文件 应用程序将发起电话呼叫 一旦接收者接听电话 应用程序应开始播放录制的音频文件 通过在谷歌上进行大量搜索 我发现这对于未root的设备来说
  • 防止 Firebase 中的待处理写入事务不起作用

    我的目标是在单击按钮时将名称插入 Cloud Firestore 中 但如果用户未连接到互联网 我不希望保存处于挂起状态 我不喜欢 Firebase 保存待处理写入的行为 即使互联网连接已恢复 我研究发现Firebase 开发人员建议使用事
  • 无法读取解析推送通知包数据

    我尝试使用 Parse 推送通知服务发送自定义数据 但从 Bundle 中提取时总是返回 null 值 自定义广播接收器 Override public void onReceive Context context Intent inten

随机推荐