当我从GetTodoRepository.fetchTodo()
调用Retrofit方法MainViewModel
并在失败或任何不成功的结果中调用结束时,我希望让RxJava同时执行onErrorReturn()
和onError()
操作,以便在这种情况下可以返回缓存的对象,但仍然通知MainViewModel
发生了错误,因此我可以显示与错误相关的UI视图。我该如何存档?
当前的代码显示了我打算如何处理它。
MainViewModel
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
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());
}
}
发布于 2020-01-28 08:34:15
Single
不能同时具有两种信号类型,但可以将fetchTodo()
转换为Observable
,并同时发出缓存项和错误:
fetchTodo()
.toObservable()
.onErrorResumeNext(error ->
Observable.just(cached)
.concatWith(Observable.error(error))
)
发布于 2020-01-28 10:31:09
我在评论中提到的第一种方法如下
为结果创建一个holder类
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>
,如下所示
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
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那样,使用可观察的方法,并背靠背地触发onNext
和onError
。
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());
}
}
然后像这样改变视图模型
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() {
}
});
https://stackoverflow.com/questions/59939802
复制相似问题