我有两个RxJava Observable,我从第一个observable获得一个arraylist,然后用它从另一个observable中获取数据。
Observable<KarobarTvVod> observable1 = youtubeDataHelper.getTVData();
observable1.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.unsubscribeOn(Schedulers.io())
.subscribe(new Subscriber<KarobarTvVod>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
e.printStackTrace();
}
@Override
public void onNext(KarobarTvVod karobarTvVod) {
Log.d(TAG, "onNext: size" + karobarTvVod.getEtag());
tvObjArrayList = new ArrayList<TVObj>();
for (int i = 0; i < karobarTvVod.getItems().size(); i++) {
TVObj tvObj = new TVObj();
tvObj.setVideoDate(karobarTvVod.getItems().get(i).getSnippet().getPublishedAt());
tvObj.setVideoIcon(karobarTvVod.getItems().get(i).getSnippet().getThumbnails().getHigh().getUrl());
tvObj.setVideoTitle(karobarTvVod.getItems().get(i).getSnippet().getTitle());
tvObj.setVideoID(karobarTvVod.getItems().get(i).getId().getVideoId());
tvObjArrayList.add(tvObj);
}
}
});
Observable<YoutubeViews> observable2 = youtubeDataHelper.getTVDataViews(tvObjArrayList);
observable2.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.unsubscribeOn(Schedulers.io())
.subscribe(new Subscriber<YoutubeViews>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
Log.d(TAG, "onError: in 2nd obs");
e.printStackTrace();
}
@Override
public void onNext(YoutubeViews youtubeViews) {
Log.d(TAG, "onNext: views" + youtubeViews.getEtag());
viewsList = new ArrayList<String>();
for (int i = 0; i < youtubeViews.getItems().size(); i++) {
viewsList.add(youtubeViews.getItems().get(i).getStatistics().getViewCount());
}
tvView.displayList(tvObjArrayList, viewsList);
}
});
这只是示例代码,我需要在从第一个Observable填充到第二个Observable时传递tvObjArrayList,这样做的最佳做法是什么?而且我在第一个Observable中使用for循环,是否有更好的方法来使用rxjava实现它?感谢
答案 0 :(得分:5)
您应该使用flatMap
运算符。它不会比那更容易。
Observable<KarobarTvVod> observable1 = youtubeDataHelper.getTVData();
observable1.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.unsubscribeOn(Schedulers.io())
.flatMap(new Func1<KarobarTvVod, Observable<YoutubeViews>>() {
@Override
public Observable<YoutubeViews> call(KarobarTvVod karobarTvVod) {
Log.d(TAG, "onNext: size" + karobarTvVod.getEtag());
tvObjArrayList = new ArrayList<TVObj>();
for (int i = 0; i < karobarTvVod.getItems().size(); i++) {
TVObj tvObj = new TVObj();
tvObj.setVideoDate(karobarTvVod.getItems().get(i).getSnippet().getPublishedAt());
tvObj.setVideoIcon(karobarTvVod.getItems().get(i).getSnippet().getThumbnails().getHigh().getUrl());
tvObj.setVideoTitle(karobarTvVod.getItems().get(i).getSnippet().getTitle());
tvObj.setVideoID(karobarTvVod.getItems().get(i).getId().getVideoId());
tvObjArrayList.add(tvObj);
}
return youtubeDataHelper.getTVDataViews(tvObjArrayList);
}
}).subscribe(new Subscriber<YoutubeViews>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
Log.d(TAG, "onError: in 1st or 2nd obs");
e.printStackTrace();
}
@Override
public void onNext(YoutubeViews youtubeViews) {
Log.d(TAG, "onNext: views" + youtubeViews.getEtag());
viewsList = new ArrayList<String>();
for (int i = 0; i < youtubeViews.getItems().size(); i++) {
viewsList.add(youtubeViews.getItems().get(i).getStatistics().getViewCount());
}
tvView.displayList(tvObjArrayList, viewsList);
}
});
答案 1 :(得分:1)
您可以使用运算符
toList().flatMap()
对于Observable A,在flatMap函数中,对Observable B起作用。
例如:
observableA
.toList()
.flatMap(observableB.subscribe())
.subscribe()
答案 2 :(得分:1)
我认为getTVData
和getTVDataViews
每个都会发出一个项目,而不是调用onComplete
。如果是,则比以下示例有效。没有loop
,只有纯rx
:)
//getTVData should emit one item and then call obComplete
//otherwise toList() will wait forever
service.getTVData()
.flatMap(karobarTvVod -> Observable.from(karobarTvVod.getItems()))
.map(item -> {
TVObj tvObj = new TVObj();
//set other fields
//by the way, I recommend you to use immutable objects
return tvObj;
})
.toList()
//here we have List<TVObj>
.flatMap(
objs -> {
//getTVDataViews should emit one item and then call onComplete
//otherwise toList will wait forever
return service.getTVDataViews(objs)
.flatMap(youtubeViews -> Observable.from(youtubeViews.getItems()))
.map(integer -> integer.toString())
//after that we will have List<String>
.toList();
},
//a function that combines one item emitted by each of the source and collection Observables
// and returns an item to be emitted by the resulting Observable
new Func2<List<TVObj>,List<String>,Pair<List<TVObj>,List<String>>>() {
@Override
public Pair<List<TVObj>, List<String>> call(List<TVObj> objs, List<String> strings) {
return new Pair(objs, strings);
}
})
.subscribe(pair -> tvView.displayList(pair.first, pair.second));
PS。虽然这种方法更简洁,但我认为loop
用于创建项目的list
效率更高。
答案 3 :(得分:0)
您需要在第一个
的onComplete中订阅第二个observable Observable<KarobarTvVod> observable1 = youtubeDataHelper.getTVData();
Observable<YoutubeViews> observable2 = youtubeDataHelper.getTVDataViews(tvObjArrayList);
observable1.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.unsubscribeOn(Schedulers.io())
.subscribe(new Subscriber<KarobarTvVod>() {
@Override
public void onCompleted() {
observable2.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.unsubscribeOn(Schedulers.io())
.subscribe(new Subscriber<YoutubeViews>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
Log.d(TAG, "onError: in 2nd obs");
e.printStackTrace();
}
@Override
public void onNext(YoutubeViews youtubeViews) {
Log.d(TAG, "onNext: views" + youtubeViews.getEtag());
viewsList = new ArrayList<String>();
for (int i = 0; i < youtubeViews.getItems().size(); i++) {
viewsList.add(youtubeViews.getItems().get(i).getStatistics().getViewCount ());
}
tvView.displayList(tvObjArrayList, viewsList);
}
});
}
@Override
public void onError(Throwable e) {
e.printStackTrace();
}
@Override
public void onNext(KarobarTvVod karobarTvVod) {
Log.d(TAG, "onNext: size" + karobarTvVod.getEtag());
tvObjArrayList = new ArrayList<TVObj>();
for (int i = 0; i < karobarTvVod.getItems().size(); i++) {
TVObj tvObj = new TVObj();
tvObj.setVideoDate(karobarTvVod.getItems().get(i).getSnippet().getPublishedAt());
tvObj.setVideoIcon(karobarTvVod.getItems().get(i).getSnippet().getThumbnails().getHigh().getUrl());
tvObj.setVideoTitle(karobarTvVod.getItems().get(i).getSnippet().getTitle());
tvObj.setVideoID(karobarTvVod.getItems().get(i).getId().getVideoId());
tvObjArrayList.add(tvObj);
}
}
});
当然为了使这段代码更具可读性,我会在onComplete方法上使用Consumer函数作为observable2.subsriberOn