首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何使RxJava调用onErrorReturn()而仍然执行onError()

如何使RxJava调用onErrorReturn()而仍然执行onError()
EN

Stack Overflow用户
提问于 2020-01-27 22:27:54
回答 2查看 1.2K关注 0票数 0

当我从GetTodoRepository.fetchTodo()调用Retrofit方法MainViewModel并在失败或任何不成功的结果中调用结束时,我希望让RxJava同时执行onErrorReturn()onError()操作,以便在这种情况下可以返回缓存的对象,但仍然通知MainViewModel发生了错误,因此我可以显示与错误相关的UI视图。我该如何存档?

当前的代码显示了我打算如何处理它。

MainViewModel

代码语言:javascript
运行
复制
public class MainViewModel extends ViewModel

    public LiveData<String> getTodo() {
    getTodoRepository.fetchTodo().subscribe(new SingleObserver<String>() {
        @Override
        public void onSubscribe(Disposable d) {
        }

        @Override
        public void onSuccess(String s) {
            showProgressAnim.setValue(false);
            todo.setValue(s);
        }

        @Override
        public void onError(Throwable e) {
            showProgressAnim.setValue(false);
            errorMsg.setValue(e.getMessage());
        }
     });
        return todo;
    }
}

GetTodoRepository

代码语言:javascript
运行
复制
public class GetTodoRepository {

    public Single<String> fetchTodo() {
        return retrofit.create(TodoApi.class)
            .getTodo()
            .doOnSuccess(s -> cacheManager.saveTodo(s))
            .onErrorReturn(throwable -> cacheManager.getTodo())
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread());
    }
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-01-28 08:34:15

Single不能同时具有两种信号类型,但可以将fetchTodo()转换为Observable,并同时发出缓存项和错误:

代码语言:javascript
运行
复制
fetchTodo()
.toObservable()
.onErrorResumeNext(error -> 
     Observable.just(cached)
     .concatWith(Observable.error(error))
)
票数 1
EN

Stack Overflow用户

发布于 2020-01-28 10:31:09

我在评论中提到的第一种方法如下

为结果创建一个holder类

代码语言:javascript
运行
复制
     class ToDoResult {

            boolean isCached;
            String todo;
            Throwable error; // this will be set only in case of error

            public ToDoResult(String todo, boolean isCached) {
                this.isCached = isCached;
                this.todo = todo;
            }

            public void setError(Throwable error) {
                this.error = error;
            }
        }

然后使您的fetchTodo()返回Single<ToDoResult>而不是Single<String>,如下所示

代码语言:javascript
运行
复制
        public class GetTodoRepository {

            public Single<ToDoResult> fetchTodo() {
                return retrofit.create(TodoApi.class)
                    .getTodo()
                    .doOnSuccess(s -> cacheManager.saveTodo(s))
                    .map(todo -> new ToDoResult(todo,false))
                    .onErrorReturn(throwable -> {
                        ToDoResult toDoResult = new ToDoResult(cacheManager.getTodo(), true);
                        toDoResult.setError(throwable);
                        return toDoResult;
                    })
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread());
            }
        }

在你身上,ViewModel

代码语言:javascript
运行
复制
     getTodoRepository.fetchTodo().subscribe(new SingleObserver<ToDoResult>() {
                @Override
                public void onSuccess(ToDoResult toDoResult) {
                    showProgressAnim.setValue(false);
                    if (toDoResult.error != null) {
                        errorMsg.setValue(toDoResult.error.getMessage());
                    } else {
                        todo.setValue(toDoResult.todo);
                    }

                }

                @Override
                public void onSubscribe(Disposable d) {

                }

                @Override
                public void onError(Throwable e) {
                    showProgressAnim.setValue(false);
                    errorMsg.setValue(e.getMessage());
                }
            });

在这种方法中,您的onError将永远不会被调用,因为我们总是将错误转换为成功信号。

第二种方法是像前面的答案中提到的per @akarnokd那样,使用可观察的方法,并背靠背地触发onNextonError

代码语言:javascript
运行
复制
 public class GetTodoRepository {

    public Observable<String> fetchTodo() {
        return  retrofit.create(TodoApi.class)
                        .getTodo()
                        .doOnSuccess(s -> cacheManager.saveTodo(s))
                        .toObservable()
                        .onErrorResumeNext(error ->
                                Observable.just(cached)
                                        .concatWith(Observable.error(error))
                        )
                        .subscribeOn(Schedulers.io())
                        .observeOn(AndroidSchedulers.mainThread());
    }

}

然后像这样改变视图模型

代码语言:javascript
运行
复制
   getTodoRepository.fetchTodo().subscribe(new Observer<String>() {
        @Override
        public void onSubscribe(Disposable d) {

        }

        @Override
        public void onNext(String s) {
             // this will be triggered with the todo item (cached in case of error)
        }

        @Override
        public void onError(Throwable e) {
           // this will be triggered followed by onNext in case of error
        }

        @Override
        public void onComplete() {

        }
    });
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59939802

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档