Подтвердить что ты не робот

В RxJava, как передать переменную вдоль цепочки наблюдаемых?

Я связываю операции async с использованием RxJava, и я хотел бы передать некоторую переменную ниже по течению:

Observable
   .from(modifications)
   .flatmap( (data1) -> { return op1(data1); })
   ...
   .flatmap( (data2) -> { 
       // How to access data1 here ?
       return op2(data2);
   })

Это похоже на общий шаблон, но я не мог найти информацию об этом.

4b9b3361

Ответ 1

Совет, который я получил от форума Couchbase, - использовать вложенные наблюдаемые:

Observable
   .from(modifications)
   .flatmap( (data1) -> { 
       return op1(data1)
           ...
           .flatmap( (data2) -> { 
               // I can access data1 here
               return op2(data2);
           })
   });

EDIT: Я буду отмечать это как принятый ответ, поскольку он кажется наиболее рекомендуемым. Если ваша обработка слишком сложна, чтобы вложить все, вы можете также проверить решение с помощью вызовов функций.

Ответ 2

Другая возможность - сопоставить результат op1 с org.apache.commons.lang3.tuple.Pair, который содержит переменную, и передать это:

Observable
   .from(modifications)
   .flatmap( (data1) -> {
       return op1(data1).map( obj -> { return Pair.of(data1,obj); });
   })
   ...
   .flatmap( (dataPair) -> { 
       // data1 is dataPair.getLeft()
       return op2(dataPair.getRight());
   })

Это работает, но кажется немного неудобным иметь переменные, скрытые внутри пары/тройной/... и он становится очень многословным, если вы используете нотацию Java 6.

Интересно, есть ли лучшее решение, может быть, может помочь какой-то оператор RxJava?

Ответ 3

Одной из возможностей было бы использовать вызов функции:

private static Observable<T> myFunc(final Object data1) {
    return op1(data1)
        ...
        .flatmap( (data2) -> { 
            // I can access data1 here
            return op2(data2);
        });
}

Observable
   .from(modifications)
   .flatmap( (data1) -> { return myFunc(data1); })

НО: исправьте меня, если я ошибаюсь, но это не похоже на способ реактивного программирования сделать это

Ответ 5

Решение

в этом потоке работает, но для сложных цепей он затрудняет чтение кода, мне нужно было передать несколько значений, а то, что я сделал, это создать частный класс со всеми параметрами, я считаю код более читаемым таким образом,

private class CommonData{
   private string data1;
   private string data2;

   *getters and setters*
}
...
final CommonData data = new CommonData();
Observable
   .from(modifications)
   .flatmap( (data1) -> { 
       data.setData1(data1);
       return op1(data1); 
   })
   ...
   .flatmap( (data2) -> { 
       data2 = data.getData1() + "data 2... ";
       data.setData2(data2);
       return op2(data2);
   })

надеюсь, что это поможет

Ответ 6

Вы можете использовать "глобальную" переменную для достижения этой цели:

 Object[] data1Wrapper = new Object[]{null};
 Object[] data2Wrapper = new Object[]{null};
 Observable
    .from(modifications)
    .flatmap(data1 -> {
        data1Wrapper[0] = data1;
        return op1(data1)
     })
      ...
    .flatmap(data2 -> { 
        // I can access data1 here use data1Wrapper[0]
        Object data1 = data1Wrapper[0];
        data2Wrapper[0] = data2;
        return op2(data2);
     })

Ответ 7

Я знаю, что это старый вопрос, но используя RxJava2 & lambda, вы можете использовать что-то вроде:

Observable
.from(modifications)
.flatMap((Function<Data1, ObservableSource<Data2>>) data1 -> {
                        //Get data 2 obeservable

                            return Observable.just(new Data2())
                        }
                    }, Pair::of)

На следующем потоке (flatmap/map) ваша выходная пара будет (data1, data2)