RxJava - 捕捉消费者例外

时间:2018-03-19 22:03:21

标签: android lambda rx-java rx-android

我目前正试图在我的Android应用程序中找到更好的网络处理解决方案。目前,我使用的是RxJava和一些src="http://maps.googleapis.com/maps/api/staticmap?center=${location.coords.lat},${location.coords.lng}&zoom=17&size=400x350&sensor=false&markers=${location.coords.lat},${location.coords.lng}&scale=2&key=AIzaSyDt0D6sy4v8BZFVJiAea93aiR63E-GpBL8"类。

消费

Consumer

NetworkConsumer

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

使用NetworkConsumer

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
}

现在,这在大多数正常情况下运行良好,例如成功登录或404错误。但是,如果有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() } }) ,例如ExceptionHttpException,则不会调用SocketTimeOutException

我发现此问题的唯一解决方案是使用另一个onFailure()来处理RxJavaPlugins中的Consumer

Exceptions

NetworkErrorConsumer

RxJavaPlugins.setErrorHandler(new NetworkErrorConsumer());

这个问题是要通知UI有错误,我需要使用事件总线将消息发送回活动。

是否有更好的解决方案可以让class NetworkErrorConsumer : Consumer<Throwable> { override fun accept(exception: Throwable) { // ... } } catch中的ExceptionsNetworkConsumer

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

谢谢!

1 个答案:

答案 0 :(得分: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风格