不调用方法doOnComplete,doOnTerminate或doOnError

时间:2019-06-12 19:43:26

标签: java android rx-java2

我有以下情况:我需要从数据库获取数据。当我尝试进入UI线程时(这是我的操作方式):

List<Movie> movies = new ArrayList<>();

for (MovieEntity movie:movieDao.getFavorites()){
    movies.add(getMovie(movie));
}
mView.onMoviesLoaded(movies);

一切正常

但是当我在rx中这样做时:

mCompositeDisposable.add(movieDao.getFavorites()
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .doOnSubscribe(disposable -> mView.showLoadingIndicator(true))
                .doOnError(throwable -> {
                    mView.showLoadingIndicator(false);
                    mView.showEmptyState(true);
                })
                .doOnTerminate(() -> mView.showLoadingIndicator(false))
                .doOnComplete(()->mView.showLoadingIndicator(false))
                .flatMapIterable(listObservable -> listObservable)
                .map(this::getMovie)
                .toList()
                .subscribe(list -> {
                    if (list.isEmpty()) {
                        mView.showEmptyState(true);
                    } else {
                        mView.onMoviesLoaded(list);
                    }
                })
        );

我一直都有加载指示器。我不明白为什么会这样,因为我为所有情况(错误和成功情况)添加了showLoadingIndicator(false)。那么,为什么它没有消失并且没有显示数据?

1 个答案:

答案 0 :(得分:1)

movieDao.getFavorites()是无限流。在无限流上使用.toList()是没有意义的,因为.toList()在源流完成之前不会发出。

有两种选择:

  1. 使您的来源有限

movieDao.getFavorites()返回Single<List<MovieEntity>>而不是Observable<List<MovieEntity>>

或在源代码后面简单插入.take(1)

mCompositeDisposable.add(movieDao.getFavorites()
                .take(1) // This will terminate the stream after it emits first item.
                .subscribeOn(Schedulers.io())
                ...
  1. 或者,不要使用.toList()

保持无限流,并继续收听数据库更改。

mCompositeDisposable.add(movieDao.getFavorites()
                .map(movieEntities -> movieEntities.stream().map(this::getMovie).collect(Collectors.toList()))
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(list -> {
                    if (list.isEmpty()) {
                        mView.showEmptyState(true);
                    } else {
                        mView.onMoviesLoaded(list);
                    }
                })
        );