java.net.SocketException: 套接字关闭未被 RxJava onError 捕获(单)

java.net.SocketException: Socket closed not caught by RxJava onError (Single)

我正在做这样的事情:在我的 Fragment 中,我正在观察 ViewModel 暴露的 LiveData,它封装了不同的 UI 状态,例如错误、加载,成功状态等。在上述 ViewModel 中,我启动了一个 RxJava2 流,该流通过 Retrofit 启动了一系列 REST API 请求:

    public LiveData<UIState> doSomething() {
        compositeDisposable.add(somethingRepo.doA()
            .andThen(somethingRepo.doB())
            .andThen(somethingRepo.doC())
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .doOnSubscribe(disposable -> status.setValue(UIState.LOADING()))
            .subscribe(() -> status.setValue(UIState.SUCCESS()), error -> {
                Log.d("SettingsVM", "error: " + error.getClass().getSimpleName());

                if(error instanceof VersionAlreadyExistsException) {
                    status.setValue(UIState.VERSION_EXISTS());
                } else {
                    status.setValue(UIState.ERROR(error.getMessage()));
                }
            })
        );
        return status;
    }

但是,根据我实现 HttpLoggingInterceptor.Logger 的自定义记录器,我在 somethingRepo.doA() 期间收到 java.net.SocketException: Socket closed,但似乎我没有在 [=21] 收到异常=] 的 onError。这是完整的 somethingRepo.doA():

public Completable doA() {
    return api.doRequest(paramRepository.getUrl(false),
        paramRepository.getAuthorization(),
        paramRepository.getName())
        .flatMapCompletable(requestResponse-> {
            if(paramRepository.getVersion().contentEquals(requestResponse.getVersion())) {
                return Completable.error(new VersionAlreadyExistsException());
            } else {
                return Completable.complete();
            }
        });
}

api.doRequest 是一个 GET 请求,如下所示:

@GET
Single<RequestResponse> doRequest (
        @Url String url,
        @Header("authorization") String authorization,
        @Query("merch") String name);

有趣的是,在另一个 Android 应用程序上,我将 POST 发送到我在上一个示例中使用的同一个 URL,而我得到的是 HTTP FAILED: java.net.ConnectException: Failed to connect to /180.232.98.122:7443

我知道一个类似的 issue being opened in the official Retrofit repo and a similar SO question here,但这两个问题尚未解决,因此我想听听这里是否有人遇到过相同的行为。

我明白问题出在哪里了。首先,我实现了一个“不活动计时器”,returns 所有屏幕(我对屏幕使用 Fragments)到我应用程序中的 first/home 屏幕。因此,假设为计时器设置了 30 秒的值,如果没有与 UI 的交互发生并且计时器达到 30 秒,那么我的应用程序将返回主屏幕。

其次,我开始请求的 ViewModelFragment 相关联,因为它实现了 DefaultLifecycleObserver,这意味着它将接收 LifecycleOwner changes/callbacks,前提是我在 Fragment#onViewCreated 中这样称呼:getViewLifecycleOwner().getLifecycle().addObserver(viewModel)。然后我在 ViewModel 中覆盖 onStop(@NonNull LifecycleOwner owner) 并调用 compositeDisposable.clear(),这意味着我想取消所有未决的 API 请求,一旦 Fragment 我使用 RxJava2 发出我的 ViewModel 绑定到接收 onStop.

最后一条信息是我的 OkHttp 客户端的超时值大于不活动计时器值,因此不活动计时器突然导致我的请求 API 在它之前被取消完成。

总而言之,会发生以下情况:当不活动计时器计时结束时,请求 API FragmentonStop 在屏幕变回主屏幕时被调用,然后 ViewModel 调用 compositeDisposable.clear() 处理当前的 RxJava 一次性,因此我无法在 onError.

上收到任何东西