【问题标题】:RxJava - Catching Consumer ExceptionRxJava - 捕获消费者异常
【发布时间】:2018-03-19 22:03:21
【问题描述】:

我目前正在尝试在我的 Android 应用程序中找到更好的网络处理解决方案。目前,我正在使用 RxJava,以及一些 Consumer 类。

消费者

public interface Consumer<T> {
    /**
     * Consume the given value.
     * @param t the value
     * @throws Exception on error
     */
    void accept(T t) throws Exception;
}

网络消费者

abstract class NetworkConsumer<T> : Consumer<NetworkResponse<T>> {

    override fun accept(response: NetworkResponse<T>) {
        if (response.isSuccessful()) {
            onSuccess(response.data)
        } else {
            onFailure()
        }
    }

    // other functions such as onSuccess and onFailure
}

使用 NetworkConsumer

UserService.login(email, password)
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(object : NetworkConsumer<LoginResponse>() {
                        override fun onSuccess(response: LoginResponse) {
                            super.onSuccess(response)
                            startMainActivity()
                        }

                        override fun onFailure() {
                            Toast.makeText(this@LoginActivity, "Could not login.", Toast.SHORT_LENGTH).show()
                        }

                    })

现在,这在大多数正常情况下都能正常工作,例如成功登录或 404 错误。但是,如果存在Exception,例如HttpExceptionSocketTimeOutException,则不会调用onFailure()

我为这个问题找到的唯一解决方案是在 RxJavaPlugins 中使用另一个处理 ExceptionsConsumer

RxJavaPlugins.setErrorHandler(new NetworkErrorConsumer());

NetworkErrorConsumer

class NetworkErrorConsumer : Consumer<Throwable> {
    override fun accept(exception: Throwable) {
        // ...
    }
}

这样做的问题是,为了通知 UI 有错误,我需要使用事件总线将消息发送回 Activity。

有没有更好的解决方案让我的catch 那些Exceptions 在我的NetworkConsumer 中?

我真的很想要一个解决方案,它允许我在调用login 时使用 Lambda 样式,而不是创建另一个对象。

谢谢!

【问题讨论】:

  • 为什么你不将这个NetworkErrorConsumer 作为subscribe() 方法的第二个参数传递?这应该捕获发生的任何异常。你可以把它作为Lamda表达式传递
  • NetworkErrorConsumer 是个好主意,但我不想将它传递给每个网络调用。有什么方法可以将所有网络错误路由到同一个位置?另外,我不能做一个 Lambda 表达式,我只能用object: NetworkErrorConsumer 语法来做。我正在尝试为此编写扩展函数,但我无法获得正确的语法。
  • 检查我的答案...

标签: android lambda rx-java rx-android


【解决方案1】:

有一个版本的subscribe() 方法接受Observer,您可以创建一个带有基本异常处理的基本方法:

abstract class NetworkObserver<T> : Observer<NetworkResponse<T>> {

    override fun onError(exception: Throwable) {
        //your base exception handling
    }

    override fun onNext(response: NetworkResponse<T>) {
        if (response.isSuccessful()) {
            onSuccess(response.data)
        } else {
            onFailure()
        }
    }

    override fun onComplete() {}

    override fun onSubscribe(d: Disposable) {}

    //onSucess & onFailure functions

}

然后为您的登录逻辑使用此类的实现:

UserService.login(email, password)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(object : NetworkObserver<LoginResponse>() {
                    override fun onNext(response: LoginResponse) {
                        super.onNext(response)
                        //additional logic
                    }

                    override fun onSuccess(response: LoginResponse) {
                        super.onSuccess(response)
                        startMainActivity()
                    }

                    override fun onFailure() {
                        Toast.makeText(this@LoginActivity, "Could not login.", Toast.SHORT_LENGTH).show()
                    }

                    //you can override onError() method if
                    //you need additional exception handling logic
                })

但是使用这种方法,您将无法使用 Lamda 样式

【讨论】:

  • 嗨 y.allam,这个解决方案似乎是一个好的开始。我正在使用飞行模式进行测试,并且在第一次尝试拨打电话时正确地引发了错误。但是,我第二次拨打电话时,它并没有被 onError 捕获。这可能是不退订的问题吗?
  • 我不这么认为,你是怎么实现的?
  • 我完全按照您的方式实现了它,它按预期工作。但是由于某种原因,当第二次调用失败时,它不会调用 onFailure。它调用onSubscribe,但不调用onFailureonComplete。例如,我有一个登录按钮。在飞行模式下,点击会显示ProgressDialog,然后按预期立即失败。但是然后再次单击该按钮不会失败,它只会订阅并使用ProgressDialog 坐在那里。
  • 这是正确的答案,问题出在我代码的其他地方。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-07-28
  • 2016-06-10
  • 1970-01-01
  • 2020-08-15
  • 1970-01-01
  • 1970-01-01
  • 2011-06-09
相关资源
最近更新 更多