架构组件改造和 RxJava 2 错误处理

Wes*_*lis 4 android retrofit2 rx-java2 android-architecture-components

我目前正在尝试使用来自改造和 Okhttp 的 API 请求在架构组件中实现新的 ViewModel,一切正常,但我不知道如何将错误响应从改造传递到片段中的观察者,然后LiveDataReactiveStreams.fromPublisher上游传递给片段中的观察者。这是我到目前为止所拥有的:

public class ShowListViewModel extends AndroidViewModel {

private final ClientAdapter clientAdapter;

private LiveData<List<Show>> shows;

public ShowListViewModel(Application application) {
    super(application);
    clientAdapter = new ClientAdapter(getApplication().getApplicationContext());

    loadShows();
}

public LiveData<List<Show>> getShows() {
    if (shows == null) {
        shows = new MutableLiveData<>();
    }

    return shows;
}

void loadShows() {
    shows = LiveDataReactiveStreams.fromPublisher(Observable.fromIterable(ShowsUtil.loadsIds())
            .subscribeOn(Schedulers.io())
            .flatMap(clientAdapter::getShowWithNextEpisode)
            .observeOn(Schedulers.computation())
            .toSortedList(new ShowsUtil.ShowComparator())
            .observeOn(AndroidSchedulers.mainThread())
            .toFlowable());
}
Run Code Online (Sandbox Code Playgroud)

在片段中,我在 OnCreate 中使用以下内容设置了 viewModel:

ShowListViewModel model = ViewModelProviders.of(this).get(ShowListViewModel.class);
    model.getShows().observe(this, shows -> {
        if (shows == null || shows.isEmpty()) {
            //This is where we may have empty list etc....
        } else {
            //process results from shows list here
        }

    });
Run Code Online (Sandbox Code Playgroud)

一切都按预期工作,但目前如果我们处于离线状态,那么改造会抛出runtimeException并崩溃。我认为问题就出在这里:

LiveDataReactiveStreams.fromPublisher(Observable.fromIterable(ShowsUtil.loadsIds())
            .subscribeOn(Schedulers.io())
            .flatMap(clientAdapter::getShowWithNextEpisode)
            .observeOn(Schedulers.computation())
            .toSortedList(new ShowsUtil.ShowComparator())
            .observeOn(AndroidSchedulers.mainThread())
            .toFlowable());
}
Run Code Online (Sandbox Code Playgroud)

通常我们会使用 rxjava2 subscribe 并捕获来自改造的错误,但是当使用LiveDataReactiveStreams.fromPublisher时,它会为我们订阅 flowable。那么我们如何将这个错误传递到这里:

model.getShows().observe(this, shows -> { //process error in fragment});

小智 5

您需要将显示和错误包装到可以保存错误的类中,而不是仅通过 LiveData 对象公开显示列表。

根据您的示例,您可以执行以下操作:

    LiveDataReactiveStreams.fromPublisher(Observable.fromIterable(ShowsUtil.loadsIds())
            .subscribeOn(Schedulers.io())
            .flatMap(clientAdapter::getShowWithNextEpisode)
            .observeOn(Schedulers.computation())
            .toSortedList(new ShowsUtil.ShowComparator())
            .observeOn(AndroidSchedulers.mainThread())
            .map(Result::success)
            .onErrorReturn(Result::error)
            .toFlowable());
Run Code Online (Sandbox Code Playgroud)

其中 Result 是保存错误或结果的包装类

final class Result<T> {

    private final T result;
    private final Throwable error;

    private Result(@Nullable T result, @Nullable Throwable error) {
        this.result = result;
        this.error = error;
    }

    @NonNull
    public static <T> Result<T> success(@NonNull T result) {
        return new Result(result, null);
    }

    @NonNull
    public static <T> Result<T> error(@NonNull Throwable error) {
        return new Result(null, error);
    }

    @Nullable
    public T getResult() {
        return result;
    }

    @Nullable
    public Throwable getError() {
        return error;
    }
}
Run Code Online (Sandbox Code Playgroud)