我试图了解Android Architecture Components
和RXJava/RXAndroid
并转换写得不好的旧项目。
我希望我的数据库成为事实的唯一来源所以我有一个MovieRepository
类来调用API,将其插入到数据库中,然后从数据库中取出电影并将其发送到ViewModel
。
我的MovieRepository类 -
public Completable getMovies(String sortPref) {
Timber.d("test repo getmovies");
if (!sortPref.equals("favorite")) {
Single<MoviesResponse> movieFlowable = movieService.getMovies(sortPref, BuildConfig.OPEN_TMDB_API_KEY);
return movieFlowable.subscribeOn(Schedulers.io())
.flatMapCompletable(moviesResponse -> {
for (MovieInfo movie : moviesResponse.getMovies()) {
movie.setPosterUrl("http://image.tmdb.org/t/p/w185/" + movie.getPosterPath());
movie.setSortSetting(sortPref);
movie.setVoterRating(movie.getRating() + "/10");
}
return insertMovies(moviesResponse.getMovies()).andThen(getMoviesFromDB(sortPref));
});
} else {
return getMoviesFromDB(sortPref);
}
}
public LiveData<List<MovieInfo>> getMoviesLiveData() {
return movies;
}
private Completable getMoviesFromDB(String sortPref) {
Timber.d("test get movies from db");
return Completable.fromAction(() -> movies = movieDatabase.getMovieDao().getMoviesBySortSetting(sortPref))
.subscribeOn(Schedulers.io());
}
private Completable insertMovies(List<MovieInfo> movies) {
Timber.d("test insert movies in db");
return Completable.fromAction(() -> movieDatabase.getMovieDao().insertAll(movies)).subscribeOn(Schedulers.io());
}
我的MovieFragmentViewModel
类的方法loadMovies()
订阅了Cold Completable。
public LiveData<List<MovieInfo>> getMovieInfo() {
if (movieInfo == null) {
movieInfo = new MutableLiveData<>();
}
return movieInfo;
}
public void loadMovies() {
// Get the Preference settings Popular is default setting
String sortPref = Utility.getPreferredSortSetting(application);
repository.getMovies(sortPref)
.observeOn(AndroidSchedulers.mainThread())
.doOnComplete(() -> movieInfo.setValue(repository.getMoviesLiveData().getValue()))
.subscribe();
}
我在ViewModel
中观察我的Fragment
就像这样 -
viewModel = ViewModelProviders.of(getActivity()).get(MovieFragmentViewModel.class);
viewModel.loadMovies();
viewModel.getMovieInfo().observe(this, movieInfos -> {
this.movies.clear();
if (movieInfos != null) {
this.movies.addAll(movieInfos);
mAdapter.notifyDataSetChanged();
}
});
根据文档,当LiveData更改时,应调用viewmodel observe方法。但是我没有在GridView中看到任何图像被加载。
我的ViewModel中的doOnComplete
方法设置了一个空的电影列表,但它应该在Completable完成后调用此Action,所以我应该有一个来自数据库的电影列表。我可以看到电影正在保存在数据库中,但没有将它们保存在我的ViewModel中。
这是我的github分支 -
https://github.com/anklinuxboy/PopularMovies2/tree/ankit/room