我有以下情况:我需要从数据库获取数据。当我尝试进入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)
。那么,为什么它没有消失并且没有显示数据?
答案 0 :(得分:1)
movieDao.getFavorites()
是无限流。在无限流上使用.toList()
是没有意义的,因为.toList()
在源流完成之前不会发出。
有两种选择:
让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())
...
.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);
}
})
);