Как перехватить наблюдаемый объект и изменить его в RxJava, прежде чем вернуться к подписчику?

В настоящее время я пытаюсь попасть в службу и вернуть список объектов, прежде чем он будет возвращен подписчику, я хочу сделать еще один синхронный вызов для каждого объекта в списке, чтобы сделать другой вызов службы для установки отсутствующего поля. Я успешно выполняю все вызовы, но объект, возвращенный в подписчике, имеет это поле, которое мне нужно установить равным null. Вот пример моего кода:

Пример сервиса:

rx.Observable<List<ExampleObject>> getExampleObject(); rx.Observable<MissingObject> getMissingObjectByFoo(@Path("foo") String foo); 

Пример:

 public class ExampleObject { String foo; MissingObject bar; public String getFoo() { return this.foo; } public void setFoo(String value) { this.foo = value; } public MissingObject getBar() { return this.bar; } public void setBar(MissingObject value) { this.bar = value; } } 

Пример реализации:

 mService.getExampleObject().flatMap(new Func1<List<ExampleObject>, Observable<?>>() { @Override public Observable<List<ExampleObject>> call(List<ExampleObject> exampleObjects) { for (ExampleObject entry : exampleObjects) { String foo = entry.getFoo(); mService.getMissingObjectByFoo(foo) .subscribeOn(mScheduler.backgroundThread()) .observeOn(mScheduler.mainThread()) .subscribe(new Subscriber<MissingObject>() { @Override public void onCompleted() { } @Override public void onError(Throwable e) { } @Override public void onNext(MissingObject missingObject) { entry.setBar(missingObject); } }); } return Observable.just(exampleObjects); }; 

Вы ищете zip оператор, как описано здесь: Zip Operator . Я думаю, вы хотите, чтобы flatmap застегнул все ваши звонки, так что примерно так:

  mService.getExampleObject().flatMap(new Func1<List<ExampleObject>, Observable<ExampleObject>>() { @Override public Observable<List<ExampleObject>> call(List<ExampleObject> exampleObjects) { List<Observable<ExampleObject>> allTheObservables = new ArrayList<Observable<ExampleObject>>(); for (ExampleObject entry : exampleObjects) { allTheObservables.add(mService.getMissingObjectByFoo(foo).map(new Func1<MissingObject, ExampleObject>() { @Override public ExampleObject call(MissingObject missingObject) { return entry.setBar(missingObject); } })); } return Observable.zip(allTheObservables, new FuncN<ExampleObject>() { @Override public ExampleObject call(ExampleObject... args) { return Arrays.asList(args); } }); } }); 

И в случае, если это не работает или возникают проблемы с синтаксисом, вот конкретный пример, используя github api:

  service.getContributorsObservable("square", "dagger") .flatMap(new Func1<List<Contributor>, Observable<List<String>>>() { @Override public Observable<List<String>> call(List<Contributor> contributors) { List<Observable<String>> allTheObservables = new ArrayList<>(contributors.size()); for (final Contributor contributor : contributors) { allTheObservables.add(service.getContributorsObservable(contributor.login).map(new Func1<User, String>() { @Override public String call(User user) { return contributor.login + " is " + user.name; } })); } return Observable.zip(allTheObservables, new FuncN<List<String>>() { @Override public List<String> call(Object... args) { return Arrays.asList((String[]) args); } }); } }); 

Имейте в виду, что это сделает n + 1 сетевых вызовов, 1 для списка ExampleObject s, а затем 1 в ExampleObject в этом списке. Если это вообще возможно, я настоятельно рекомендую вам поговорить с сопровождающим API, чтобы получить информацию о поиске по сторонам API. Просто знайте, что это будет использовать некоторую пропускную способность!

Поскольку ваш посреднический вызов для обновления записи является асинхронным, я не думаю, что вы можете использовать List<ExampleObject> , но вместо этого следует использовать ExampleObject непосредственно из Observable :

 mService.getExampleObject() // Spread the list .flatMap(list -> Observable.from(list)) // Update your object // Here we zip the object with the missing object, // so that when the missing object is obtained, // we update the entry and emit it. .flatMap(entry -> Observable.zip( Observable.just(entry), mDocsService.getMissingObjectByFoo(entry.getFoo()), (entry, missingObject) -> { entry.setBar(missingObject); return entry; }) ) // if you really want a map after all .toList(); 

Примечание:

Вы можете пропустить zip, если вы в порядке, если функция на map зависит от внешней переменной (записи). Этого я пытаюсь избежать, но здесь все равно:

  .flatMap(entry -> mDocsService.getMissingObjectByFoo(entry.getFoo()) .map(missingObject -> { entry.setBar(missingObject); return entry; }) ) 
Intereting Posts
Веб-просмотр загрузки локальной html-страницы медленно в Android Android: я потерял свой магазин ключей для Android, что мне делать? Плохое качество изображения после изменения размера / масштабирования растрового изображения Как сделать заявку SSO для Android и приложений IPhone с помощью ADFS STS? Ошибка PagerSlidingTabStrip при открытии Android lint.xml doctype с объявлением dtd Android: как динамически изменять атрибуты темы во время выполнения из кода Начните свое приложение с genymotion Как я могу проверить поддержку Wi-Fi устройства Android? Есть ли способ протестировать приложение на реальном устройстве без публикации? Календарное событие сохраняется локально на телефоне, но не может синхронизироваться с Календарем Google. Нельзя ссылаться на другой идентификатор просмотра в привязке данных Android Изменение цвета Horizonal Progress в Android Spotify Intent в android? Сортировка коллекции по нескольким полям в Котлине