#android #rx-java
#Android #rx-java
Вопрос:
Я новичок в RxJava, и у меня от этого кружится голова. По сути, я извлекаю данные из api youtube с помощью retrofit, который возвращает Observable, а с помощью youtubeDataMapper я отображаю их в объект Youtube Pojo, который содержит строку VideoID. Итак, мой вопрос в том, как заставить этот метод возвращать эту строку вместо завершаемой?
Это мой метод:
@Override
public Completable downloadVideoUrl(String query) {
addSubscription(youtubeApi.getYoutubeId(query, Constants.youtubeApi)
.map(youtubeDataMapper::map)
.subscribeOn(subscribeScheduler)
.observeOn(observeScheduler)
.subscribe());
return Completable.complete();
}
Ответ №1:
У вас есть два варианта:
-
Сделайте свой
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()
Это не предпочтительно, поскольку вы блокируете current
Thread
доObservable
завершения@Override public String downloadVideoUrl(String query) { return youtubeApi.getYoutubeId(query, Constants.youtubeApi) .map(youtubeDataMapper::map) .subscribeOn(subscribeScheduler) .observeOn(observeScheduler) .toBlocking().first(); }
Ответ №2:
Прежде всего, лучше сделать Retrofit return 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);
}
}