如何捕获UnknownHostException单个一次性订阅

时间:2019-04-01 10:37:20

标签: java android rx-java2

我需要使用RxJava2在一个特定的网络调用的Disposable .subscribe方法内捕获一个UnknownHostException。

在我的一个Android应用程序中,我遇到了一个非常随机发生的错误,这使我花了很长时间才能在该字段中进行复制。我可以将其与开普敦的不可靠的网络/ SIM卡连接相关,我们在该处将应用程序部署到数百个用户。仿真器或我在德国测试过的任何电话都不会发生该错误。

当我从Wifi切换到移动数据,关闭移动数据/ wifi或进入飞行模式时,所有经典测试用例均由应用正确处理。

该应用程序多次发出API请求,并通过FCM接收数据。他们都工作正常。但是,当您打开应用程序时,有一个请求发送状态更新。暂时存在网络问题时,此请求将失败。我目前正在开普敦进行测试,这些网络问题是如此短暂和频繁,以至于Android无法以标准方式来快速处理它们,从而无法处理不可用的连接。我可以看到每周一次或两次使用数百部24/7运行的电话出现该问题。

这是引起麻烦的方法。我可以用注释掉的行来引起错误。这将使启动屏幕永久显示进度对话框。

    public void sendActiveGuardStatus() {
        GuardManager guardManager = GuardManager.newInstance(getBaseContext());
        showProgress("Loading Operation Status");
        Disposable subscription = guardManager
                .setGuardAvailable()
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .timeout(8, TimeUnit.SECONDS)
                .onErrorReturn(e -> {return null;})
                .subscribe(
                        response -> {
//                            if (Math.random() < 0.5) {
//                                throw new UnknownHostException("Oh no, no network...");
//                            }
                            hideProgress();
                            startHomeActivity();
                        }
                        , throwable -> {
                            hideProgress();
                            startLoginActivity();
                        }
                );

        addSubscription(subscription);
    }

这是构建请求的方式:

public class GuardManager {

    public static GuardManager newInstance(Context context) {
        return new GuardManager(
                context,
                RetrofitFactory.build(context).create(GuardNetworkService.class),
                new GuardUtils()
        );
    }

...

    public Single<SetGuardStatusResponse> setGuardAvailable() {
        return networkService
                .setGuardStatus("available")
                .compose(response -> TokenErrorTransformer.withErrorCheck(response, context));
    }

...
}
  public interface GuardNetworkService {
  ...

    @PUT("guardian/set_status_{guard_status}")
    Single<SetGuardStatusResponse> setGuardStatus(@Path("guard_status") String status);

  ...
}

我想捕获在.subscribe(...)内部创建的异常,并在外部进行手动处理。最后,我要重试3次,两次请求之间要有延迟。

我尝试了onError()以及我能想到的所有try / catch组合,但最终总是遇到这样的异常:

2019-04-01 12:00:37.682 11683-11683/com.lionizers.guardapp W/System.err: io.reactivex.exceptions.UndeliverableException: java.net.UnknownHostException: Oh no, no network...
2019-04-01 12:00:37.682 11683-11683/com.lionizers.guardapp W/System.err:     at io.reactivex.plugins.RxJavaPlugins.onError(RxJavaPlugins.java:367)
2019-04-01 12:00:37.682 11683-11683/com.lionizers.guardapp W/System.err:     at io.reactivex.internal.observers.ConsumerSingleObserver.onSuccess(ConsumerSingleObserver.java:66)

我知道我可以使用RxJavaPlugins.setErrorHandler,但是我不知道如何使用该代码专门重试此单个请求。所有其他请求都通过任务/线程进行管理,因此对于代码的任何其他部分,我都不需要通用的错误处理程序。

  1. 我在概念上缺少什么吗?有更好的方法进行吗?
  2. 如何捕获此特定订阅方法中引发的异常?

0 个答案:

没有答案