首先,让我先说一下我对RxJava比较陌生,所以请在掌握基础知识时请耐心等待。 :)
我基本上了解整个subscribe[On|With]()
初学者类型的东西(或多或少)。我正在尝试做一些有点复杂的事情,JavaRx似乎非常适合这种事情。
我有一个策划的电影数据库,我正在查询电影细节。现在,这里的API有点奇怪。您必须拨打两个电话才能获得有关电影的所有内容。第一个API调用产生id,标题,类别和评级以及第二个其他重要的东西,如描述,预告片等。正如您可能已经猜到的,您需要来自part1的movieId
来获取额外的信息。这里嵌套的调用工作,但它们绝不是最佳实践。
我的代码看起来像这样:
pageSingle.subscribeOn(Schedulers.io())
.subscribeWith(new DisposableSingleObserver<mPage>() {
@Override public void onSuccess(mPage value) {
moviesInPage = value.movies;
if(moviesInPage==null){
Log.w(TAG, "mergeMovieParts: no movies returned");
}else {
for (int i = 0; i < moviesInPage.size(); i++) {
final fMovie firstMovie = moviesInPage.get(i);
apiService.getSecondPart(firstMovie.id)
.subscribeWith(new DisposableSingleObserver<sMovie>() {
@Override
public void onSuccess(sMovie secondMovie) {
mergeMovieParts(firstMovie, secondMovie);
}
@Override
public void onError(Throwable e) {
e.printStackTrace();
}
});
}
}
}
@Override public void onError(Throwable e) {
handleError(e);
}
});
pageSingle
也是Single
。
你可能会发现为什么不能保证一直都能正常工作。 Single.zip()
在这里不起作用,因为我需要从第一次调用开始第二次调用的信息(更具体地id
)。我的问题归结为:
如何用JavaRx替换那些嵌套的Retrofit调用
那些?请注意mPage
会返回List<fMovie>
个对象。
此刻,我一个接一个地打这些电话。是吗 可以获取电影列表并基于此来制作多个 同时调用以获取第二部分?我正在猜测 多线程就是这里的答案,但我该怎么做呢 RxJava有什么影响,例如:是不值得的,在你的 意见或是对大的权衡(如果有的话)?
与此问题无关,但您有什么建议吗? 书籍,视频等我可以阅读/观看,这将有助于我赶上 与RxJava最多。它激动了我很多,但与此同时我 觉得通过“阅读”来学习所有内容有点过于庞大 文档”。
如果我不够清楚,请不要犹豫,要求更多背景/澄清。提前谢谢!
编辑:flatMap()
错误:
Error:(109, 17) error: no suitable method found for flatMap(<anonymous Function<Movie1,ObservableSource<?>>>)
method Observable.<R#1>flatMap(Function<? super Object,? extends ObservableSource<? extends R#1>>) is not applicable
(cannot infer type-variable(s) R#1
(argument mismatch; <anonymous Function<Movie1,ObservableSource<?>>> cannot be converted to Function<? super Object,? extends ObservableSource<? extends R#1>>))
method Observable.<R#2>flatMap(Function<? super Object,? extends ObservableSource<? extends R#2>>,boolean) is not applicable
(cannot infer type-variable(s) R#2
(actual and formal argument lists differ in length))
method Observable.<R#3>flatMap(Function<? super Object,? extends ObservableSource<? extends R#3>>,boolean,int) is not applicable
(cannot infer type-variable(s) R#3
(actual and formal argument lists differ in length))
method Observable.<R#4>flatMap(Function<? super Object,? extends ObservableSource<? extends R#4>>,boolean,int,int) is not applicable
[...]
我的实施:
movieService.getMoviesFromPath(path)
.subscribeOn(Schedulers.io())
.flattenAsObservable(new Function<MoviePage, Iterable<?>>() {
@Override
public Iterable<?> apply(MoviePage moviePage) throws Exception {
return moviePage.movieList; // movieList is a List<Movie1>
}
})
.flatMap(new Function<Movie1, ObservableSource<?>>() {
@Override
public ObservableSource<?> apply(Movie1 movie1) throws Exception {
return null;
}
});
答案 0 :(得分:1)
您似乎需要以下内容:
movieService.getPage()
.flattenAsObservable(page -> page.movies)
.flatMap(movie -> apiService.getSecondPart(movie.movieId))
或者,带走了lambdas,
movieService.getPage()
.flattenAsObservable(new Function<Page, Iterable<Movie>>() {
@Override
public Iterable<Movie> apply(Page page) throws Exception {
return page.movies;
}
})
.flatMap(new Function<Movie, ObservableSource<DetailedMovie>>() {
@Override
public ObservableSource<DetailedMovie> apply(Movie movie) throws Exception {
return apiService.getSecondPart(movie.movieId);
}
})
话虽如此,在原帖中写new DisposableSingleObserver<mPage>
之类的东西是个坏兆头。在继续使用Rx之前,可能值得花时间学习Generics in Java,因为这是导致第二次错误的原因。
您可能需要具备良好的泛型工作知识(and standard Java naming practices)才能充分利用RxJava。祝你好运!
请注意,这两个示例假定subscribeOn(Schedulers.io())
是隐式的并且在Retrofit级别配置。您可以看到如何执行此操作in these answers
更新:如果你想将两个Movie对象合并在一起,我想你可以这样做:
movieService.getPage()
.flattenAsObservable(new Function<Page, Iterable<? extends Movie>>() {
@Override
public Iterable<? extends Movie> apply(Page page) throws Exception {
return page.movies;
}
})
.flatMap(new Function<Movie, ObservableSource<DetailedMovie>>() {
@Override
public ObservableSource<DetailedMovie> apply(Movie movie) throws Exception {
return apiService.getSecondPart(movie.movieId).toObservable();
}
}, new BiFunction<Movie, DetailedMovie, MergedMovie>() {
@Override
public MergedMovie apply(Movie movie, DetailedMovie detailedMovie) throws Exception {
return new MergedMovie(movie, detailedMovie);
}
});