Как передать вывод сингла в RxJava для завершения? - PullRequest
0 голосов
/ 05 декабря 2018

Я хочу вызвать API api1 и передать результат, возвращенный API, второму API api2.Первый API - это запрос get, а второй API - запрос POST.Поэтому api1 возвращает Single<String>, а api2 возвращает Completable.

Функции выглядят примерно так:

// api1
public Single<String> getToken() {
  ...
}
// api2
public Completable saveTokenToBackend(String token, String userId) {
 ...
}

Я хочу объединить оба этиоперации вместе.Подписчик заинтересован только в том, чтобы узнать, прошел ли процесс получения токена и сохранить его успешно или нет.Следовательно, тип возвращаемого значения последней цепочки операций должен быть Completable.Однако, когда я делаю это, API вызывает api2, перестает происходить.Только api1 успешно работает в соответствии с журналами.

Single<Completable> r1 = getToken().map(t -> saveTokenToBackend(t, userId));
Completable r2 = Completable.fromSingle(r1);

Мой более широкий вопрос здесь заключается в том, как мне соединить ответ от простого к завершаемому?

Второй вопрос: почему вышеуказанный код не работает?

:: EDIT ::

Основываясь на предложениях в комментариях, я попытался:

public Completable getAndSaveToken() {
    getToken().flatMapCompletable(t -> saveTokenToBackend(t, "dummyuser");
}

В моем коде приложения я делаю:

getAndSaveToken()
   .subscribeOn(Schedulers.io())
   .observeOn(AndroidSchedulers.mainThread())
   .subscribe(() -> {
                Log.v(TAG, "call success");
    }, error -> {
                Log.e(TAG, "Error", error);
    });

Результаты в: java.io.IOException: Must not be called on the main application thread

1 Ответ

0 голосов
/ 05 декабря 2018

У вас есть 2 разные задачи, состав и планирование.Контекст: getToken возвращает одиночный код, а saveToken(token) возвращает завершаемый.

состав : для создания одного и завершаемого, как вы уже заметили, вы можете использовать оператор flatMapэто возвращает новый завершаемый файл, который сначала получает токен, а затем сохраняет его (возможно, вы захотите изменить токен перед его сохранением;)

getToken().flatMapCompletable(n -> saveToken(n)) // returns a completable

Если вы хотите сохранить его как один, так что вы можете сопоставить его с первым экземпляром:

getToken().flatMap(n -> saveToken(n).toSingleDefault(n)) // returns a single

планирование : в Android вы не должны запускать запрос в главном потоке.Чтобы избежать этого, вы можете использовать оператор subscribeOn, также похоже, что вы уже заметили, что

getToken().subscribeOn(io()).doOnNext(n -> {/*this should be evaluated in io thread*/})
getToken().subscribeOn(io()).observeOn(mainThread()).doOnNext(n -> {/*this on mainThread*/})

Если вы по-прежнему получаете сообщение об ошибке, то observeOn или subscribeOn был перенастроенгде-то.Нужно больше кода, чтобы быть уверенным.Но в любом случае, вы можете утверждать, что оба запроса выполняются в потоке io, применяя оператор дважды:

getToken().subscribeOn(io).flatMapCompletable(token -> saveToken(token).subscribeOn(io()))

Другой вариант, если вы используете модернизацию, это применить RxJava2CallAdapterFactory с помощью createWithScheduler(io())заводская, вместо стандартной.Это подтвердит, что все запросы создаются в io (), так что вы можете объединить и подготовить данные, и, наконец, применить observeOn(mainThread()) для обновления пользовательского интерфейса.

...