В RxJava, как передать переменную вдоль цепочки наблюдаемых?
Я связываю операции async с использованием RxJava, и я хотел бы передать некоторую переменную ниже по течению:
Observable
.from(modifications)
.flatmap( (data1) -> { return op1(data1); })
...
.flatmap( (data2) -> {
// How to access data1 here ?
return op2(data2);
})
Это похоже на общий шаблон, но я не мог найти информацию об этом.
Ответы
Ответ 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); })
НО: исправьте меня, если я ошибаюсь, но это не похоже на способ реактивного программирования сделать это
Ответ 4
flatmap может принимать второй аргумент:
Observable.just("foo")
.flatMap(foo -> Observable.range(1, 5), Pair::of)
.subscribe(pair -> System.out.println("Result: " + pair.getFirst() + " Foo: " + pair.getSecond()));
источник: https://medium.com/rxjava-tidbits/rxjava-tidbits-1-use-flatmap-and-retain-original-source-value-4ec6a2de52d4
Ответ 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)