[java] RxJava에서 Observable을 연결할 때 변수를 전달하는 방법은 무엇입니까?

RxJava를 사용하여 비동기 작업을 연결하고 있으며 몇 가지 변수를 다운 스트림으로 전달하고 싶습니다.

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

일반적인 패턴처럼 보이지만 정보를 찾을 수 없습니다.



답변

Couchbase 포럼에서 얻은 조언은 중첩 된 Observable을 사용하라는 것입니다.

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

편집 : 가장 권장되는 것처럼 보이므로 수락 된 답변으로 표시하겠습니다. 처리가 너무 복잡해서 모든 것을 중첩 할 수없는 경우 함수 호출로 솔루션을 확인할 수도 있습니다.


답변

또 다른 가능성은 결과 매핑하는 것이다 op1A와 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());
   })

작동하지만 Pair / Triple / … 안에 변수를 숨기는 것이 약간 불편하고 Java 6 표기법을 사용하면 매우 장황 해집니다.

더 나은 솔루션이 있는지 궁금합니다. RxJava 연산자가 도움이 될 수 있습니까?


답변

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


답변

한 가지 가능성은 함수 호출을 사용하는 것입니다.

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); })

하지만 내가 틀렸다면 정정 해 주지만 반응 프로그래밍 방식이 아닌 것 같습니다.


답변

사실 우리는 콜 체인을 단순화하는 라이브러리를 가지고 있습니다.

https://github.com/pakoito/Komprehensions

Gradle 종속성으로 추가 :

implementation 'io.reactivex.rxjava2:rxjava:2.2.1'
implementation 'com.github.pakoito.Komprehensions:komprehensions-rx2:1.3.2'

사용법 (Kotlin) :

val observable = doFlatMap(
    { Observable.from(modifications) },
    { data1 -> op1(data1) },
    { data1, data2 -> op2(data2) },
    { data1, data2, data3 -> op3(data1, data2, data3) }
)


답변

이 스레드에 대한 솔루션은 작동하지만 복잡한 체인의 경우 코드를 읽기 어렵게 만들고 여러 값을 전달해야했고 모든 매개 변수가있는 개인 클래스를 만드는 것이 었습니다.이 방법으로 코드를 더 읽기 쉽게 찾을 수 있습니다.

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);
   })

도움이 되길 바랍니다


답변

나는 이것이 오래된 질문이라는 것을 알고 있지만 RxJava2 및 람다를 사용하면 다음과 같이 사용할 수 있습니다.

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

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

다음 흐름 (플랫 맵 / 맵)에서 출력 쌍은 (data1, data2)입니다.