我是rxJava的新手,它让我头晕目眩。基本上我用retrofit从youtube api中提取数据,它给出了Observable,用youtubeDataMapper,我把它映射到youtube Pojo对象,它包含String videoID。我的问题是,如何让这个方法返回那个字符串而不是Completable?
这是我的方法
@Override
public Completable downloadVideoUrl(String query) {
addSubscription(youtubeApi.getYoutubeId(query, Constants.youtubeApi)
.map(youtubeDataMapper::map)
.subscribeOn(subscribeScheduler)
.observeOn(observeScheduler)
.subscribe());
return Completable.complete();
}
你有两个选择:
-
让你的
downloadVideoUrl
返回Observable
而不是Completable
:首选方法:
@Override public Completable downloadVideoUrl(String query) { return youtubeApi.getYoutubeId(query, Constants.youtubeApi) .map(youtubeDataMapper::map) .subscribeOn(subscribeScheduler) .observeOn(observeScheduler); }
注意这里缺少
subscribe
运算符。然后在你想要获取videoId的地方:
downloadVideoUrl(query) .subscribe(new Subscriber<String>() { @Override public void onCompleted() { } @Override public void onError(Throwable e) { } @Override public void onNext(String videoId) { // do whatever you want with videoId } });
-
使用
toBlocking().first()
这不是首选,因为你会阻塞当前的
Thread
直到Observable
完成@Override public String downloadVideoUrl(String query) { return youtubeApi.getYoutubeId(query, Constants.youtubeApi) .map(youtubeDataMapper::map) .subscribeOn(subscribeScheduler) .observeOn(observeScheduler) .toBlocking().first(); }
首先,最好让Retrofit返回Single而不是Observable,因为你期望的是单个服务器响应(而不是一系列响应)。
其次,Completable.complete()是Completable的工厂方法,它什么都不做。所以你不需要它在这里。
关于字符串videoID,它取决于你打算用它做什么。另外,我不知道你的。addsubscription()在做什么。
我建议这样做:
class YourClass {
private final CompositeSubscription compositeSubscription = new CompositeSubscription();
// you must call compositeSubscription.clear() either in class .finalize() or on some UI lifecycle event
void yourMethod() {
final Single videoID = youtubeApi.getYoutubeId(query, Constants.youtubeApi)
.map(youtubeDataMapper::map)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());
final Subscription subscription = videoID.subscribe(new SingleSubscriber() {
@Override
public void onSuccess(String value) {
// TODO: do whatever with the value
}
@Override
public void onError(Throwable error) {
// TODO: log and/or display error
}
});
compositeSubscription.add(subscription);
}
}