6

State의 다른 구현을 위해 다른 관찰 가능한 로직 체인을 처리하고 싶습니다. 이것은 봉인 된 클래스/대수 데이터 형식/공용체 + .flatMap()을 사용하여 쉽게 얻을 수 있지만 .distinctUntilChanged()과 같은 연산자가 .flatMap() 함수 내에서만 작동하고 전체 스트림에서는 작동하지 않는 스트림이 중단됩니다. 스트림 자체.반응이없는 스트림을 끊는 .flatMap없이 플로우를 제어하는 ​​방법. distinctUntilChanged와 같은 연산자가 전체 스트림에서 작동하지 못하도록합니다.

sealed class State { 
    object Loading : State() 
    data class Loaded(val value: Int) : State() 
} 

@Test fun distinctTest() { 
    val relay = PublishRelay.create<State>() 
    relay.flatMap { 
     fun handle(state: State): Observable<*> = when (state) { 
      State.Loading -> Observable.just(state) 
        .distinctUntilChanged() 
        .doOnNext { println("loading") } 

      is State.Loaded -> Observable.just(state) 
        .distinctUntilChanged() 
        .doOnNext { println(it.value) } 
     } 
     handle(it) 
    } 
      .subscribe() 

    relay.accept(State.Loading) 
    relay.accept(State.Loaded(1)) 
    relay.accept(State.Loaded(2)) 
    relay.accept(State.Loaded(3)) 
    relay.accept(State.Loaded(3)) 
    //desired: loading, 1, 2, 3 
    //actual: loading, 1, 2, 3, 3 
} 

참고 : 이것은 단순화 된 예입니다. 지금 막 인쇄 중일 때 구현 유형 State을 기반으로 다른 동작을 실제로 수행하려고합니다 (State)

이 작업은 제목/릴레이를 사용하여 수행 할 수는 있지만 연결이 끊긴, 나는 또한 피하고 싶다.

+0

위대한 질문 친구! – Everett

+1

당신은'relay' 옆에'distinctUntilChanged'를 움직일 것을 고려 했습니까? : relay.distinctUntilChanged.flatMap ...'? –

+0

@ m.ostroverkhov 확실히,하지만 그건 내 유스 케이스 아니에요. 전체 스트림에서 작업하려면'distinctUntilChange'가 필요합니다. 귀하의 제안은 flatmap 내에서 작동하지 않는 distinctUntilChanged를가집니다. 둘 다 갖는 것은 유스 케이스에서 너무 비싸다. – ZakTaccardi

답변

0

Observable을 여러 개의 관찰 가능 항목으로 나누어 각각 하나의 이벤트 유형을 얻을 수 있습니까? 그런 다음 이들 관측 자료를 다시 병합하기 전에 이러한 관측 자료에 대해 몇 가지 작업을 수행 할 수 있습니다.

지금은 테스트 할 수 없으므로 약간의 조정이 필요할 수 있습니다. 어쨌든 여기서 아이디어를 얻으시기 바랍니다 :

@Test fun distinctTest() { 
    val relay = PublishRelay.create<State>() 

    val loadingObs = relay.filter { it is State.Loading } 
          .distinctUntilChanged() 
          .doOnNext { println("loading") } 

    val loadedObs = relay.filter { it is State.Loaded } 
         .distinctUntilChanged() 
         .doOnNext { println(it.value) } 

    val merged = loadingObs.mergeWith(loadedObs) 

    merged.subscribe() 

    relay.accept(State.Loading) 
    relay.accept(State.Loaded(1)) 
    relay.accept(State.Loaded(2)) 
    relay.accept(State.Loaded(3)) 
    relay.accept(State.Loaded(3)) 
    // Hopefully prints this: loading, 1, 2, 3 
}