RxJava 2, Retrofit 2 + Retrolambda - объединение 2 запросов в цепочку

Первый вызов API возвращает список элементов, а затем я хочу впоследствии вызвать другой API с String, возвращенным в каждом элементе списка из первого вызова API. Я (думаю, у меня) получил это так, что он вызывает второй вызов API с каждым элементом списка, но я не уверен, как затем подписаться на него, чтобы получить результаты, возвращенные от второго вызова.

discogsService.getSearchResults(searchTerm, mContext.getString(R.string.token))
                .observeOn(AndroidSchedulers.mainThread())
                .subscribeOn(Schedulers.io())
                // Turns the result into individual elements
                .flatMapIterable(RootSearchResponse::getSearchResults)
                // I believe this then calls .getRelease() with each ID string
                .map(result -> discogsService.getRelease(result.getId()));

Модернизация интерфейса:

public interface DiscogsService
{
    @GET("database/search?")
    Observable<RootSearchResponse> getSearchResults(@Query("q") String searchTerm, @Query("token") String token);

    @GET("releases/")
    Observable<Release> getRelease(@Query("release_id") String releaseId);
}

Я не знаю, куда идти дальше.

Я считаю, что .subscribe(...) тогда дает мне возможность получить Observable<Release>, возвращенный от каждого .getRelease(...). Поскольку вышеупомянутый метод вызывается на уровне модели, мне затем нужно настроить подписчика на этом уровне модели для передачи обратно Presenter, а затем дополнительного подписчика в Presenter для работы с каждым Observable, поскольку Presenter имеет доступ к View.

Есть ли способ, чтобы я мог просто вернуть каждый Observable из уровня модели, чтобы мне не нужно было иметь два отдельных .subscribe(...)? Или мне следует использовать два отдельных .subscribe(...), так как тогда я могу обнаруживать ошибки на обоих из них? Мне нужны только результаты второго звонка.

Вот полный код, который я пробовал:

В модели:

discogsService.getSearchResults(searchTerm, mContext.getString(R.string.token))
                .observeOn(AndroidSchedulers.mainThread())
                .subscribeOn(Schedulers.io())
                .flatMapIterable(RootSearchResponse::getSearchResults)
                .subscribeOn(Schedulers.io())
                .map(result -> discogsService.getRelease(result.getId()))
                .subscribe(new Observer<Observable<Release>>()
                {
                    @Override
                    public void onSubscribe(Disposable d)
                    {

                    }

                    @Override
                    public void onNext(Observable<Release> value)
                    {
                        mainPresenter.addToRecyclerView(value);
                    }

                    @Override
                    public void onError(Throwable e)
                    {

                    }

                    @Override
                    public void onComplete()
                    {

                    }
                });

В Presenter:

@Override
public void addToRecyclerView(Observable<Release> value)
{
    value       .observeOn(AndroidSchedulers.mainThread())
                .subscribeOn(Schedulers.io())
                .subscribe(new Observer<Release>()
                {
                    @Override
                    public void onSubscribe(Disposable d)
                    {

                    }

                    @Override
                    public void onNext(Release value)
                    {
                        Log.e(TAG, "Success! " + value);
                        results.add(value);
                    }

                    @Override
                    public void onError(Throwable e)
                    {
                        Log.e(TAG, "Error: " + e.toString());
                        Log.e(TAG, "Error: " + e.toString());
                    }

                    @Override
                    public void onComplete()
                    {

                    }
                });

person Josh Laird    schedule 19.02.2017    source источник
comment
Я прочитал ваш вопрос 5 раз и не смог его понять. Вы можете это перефразировать?   -  person Divers    schedule 19.02.2017
comment
Пожалуйста, покажите, как вы использовали subscribe, потому что это то, что вам нужно сделать. Опишите нежелательные результаты примером, по крайней мере   -  person OneCricketeer    schedule 19.02.2017
comment
вы хотите подписаться на оба вызова веб-сервиса и получить результат обоих из них, а затем что-то сделать с результатом?   -  person MBH    schedule 19.02.2017
comment
Извините, ребята, первая попытка RxJava - обновили OP   -  person Josh Laird    schedule 19.02.2017


Ответы (1)


Я бы предпочел выставить Observable<Release> на уровне модели:

Observable<Release> getReleases(...) {
    return discogsService.getSearchResults(...)
        .flatMapIterable(RootSearchResponse::getSearchResults)
        .flatMap(result -> discogsService.getRelease(result.getId()));
}

Ведущий просто подписывался на него:

getReleases
    .observeOn(AndroidSchedulers.mainThread())
    .subscribeOn(Schedulers.io())
    .subscribe(new Observer<Release>()
    {
        @Override
        public void onSubscribe(Disposable d)
        {

        }

        @Override
        public void onNext(Release value)
        {
            Log.e(TAG, "Success! " + value);
            results.add(value);
        }

        @Override
        public void onError(Throwable e)
        {
            Log.e(TAG, "Error: " + e.toString());
            Log.e(TAG, "Error: " + e.toString());
        }

        @Override
        public void onComplete()
        {

        }
    });

Только одно наблюдаемое. Обратите внимание на переключение с map() на flatMap() для второго запроса в getReleases(...). За кадром здесь происходит вторая подписка.

Последний подписчик получит ошибки от обоих запросов. Я предпочитаю позволить потребителю (докладчику) обрабатывать ошибки, потому что это тот, кто заботится об ответе и знает, что делать в случае ошибки (например, отображать сообщение).

Это тот, кто «управляет» Observable, кто его создает, утилизирует, так что его обязанность - назначить поток imho.

Observable очень хорошо подходят для перехода от одного слоя к другому. Он описывает тип данных, способ их использования и шаблон (наблюдаемые? Одиночные? Текучие?).

person Geoffrey Marizy    schedule 20.02.2017