2015-07-08 12 views
10

Nehmen wir an, ich habe zwei unendliche Observables, die jederzeit Werte ausgeben können. Sie kombinieren, um eine Observable<ProcessFileEvent> zu erstellen.RxJava - CombineNeueste, aber nur Feuer für eine Observable-Emission?

Observable<Integer> selectedFileId= ... 
Observable<MouseClick> buttonClick = ... 

Observable<ProcessFileEvent> `processFileEvent` = Observable.combineLatest(selectedFileId, buttonClick, (s,b) -> { 
    //create ProcessFileEvent here 
}); 

Das Problem ist, ich will nur das processFileEvent zu emittieren, wenn buttonClick etwas abgibt, nicht selectedFileId. Es ist definitiv nicht das Verhalten, das ein Benutzer erwartet, wenn eine Datei-ID eingegeben wird, und es startet eine ProcessFileEvent. Wie kombiniere ich aber nur wenn die buttonClick ausstrahlt?

Antwort

3

Verwenden Sie .distinctUntilChanged() auf dem Objekt MouseClick. Auf diese Weise erhalten Sie nur Ereignisse, wenn sich die MouseClick ändert.

Erstellen Sie eine Klasse, die sowohl fileId und mouseClick enthält:

static class FileMouseClick { 
    final int fileId; 
    final MouseClick mouseClick; 

    FileMouseClick(int fileId, MouseClick mouseClick) { 
     this.fileId = fileId; 
     this.mouseClick = mouseClick; 
    } 
} 

Dann

Observable.combineLatest(selectedFileId, buttonClick, 
         (s,b) -> new FileMouseClick(s,b)) 
    .distinctUntilChanged(f -> f.mouseClick) 
    .map(toProcessFileEvent()) 
+0

Dies ist sinnvoll. Eine kurze Frage. Basiert 'distinct()' auf 'hashcode()/equals()' für jedes ausgegebene Objekt oder unterdrückt es Dupe-Sequenzen? – tmn

+1

Ein HashSet wird intern verwendet. Wenn Sie hashCode()/equals() für MouseClick implementiert haben, ist es besser, was Sie wollen. Wenn Sie sie nicht implementiert haben, wird nur die Objektreferenzgleichheit verwendet. Oh, das ist Overkill Ich habe gerade erkannt, dass wir distinctUntilChanged verwenden müssen. Ich werde aktualisieren. –

+0

Nun, da distinctUntilChanged verwendet wird, ist kein HashSet beteiligt, aber die equals() -Methode wird für die separate Prüfung verwendet, so dass Sie sich immer noch wie gewünscht hashCode()/equals() verhalten müssen. –

1

Sie können dazu Observable.Join verwenden. Achten Sie besonders auf diesen Absatz:

Doch was könnte ich tun, um sicherzustellen, dass diese Fenster nicht überlagernde taten so, dass, sobald ein zweiter Wert erzeugt wurde ich würde nicht mehr den ersten Wert sehen? Nun, wenn wir die linke Sequenz von der leftDurationSelector zurückgeben, könnte das den Trick machen. Aber warten Sie, wenn wir die vom leftDurationSelector übrig gelassene Folge zurückgeben, würde es versuchen, eine andere Subskription zu schaffen und das kann Nebenwirkungen einführen. Die schnelle Antwort darauf ist Veröffentlichen und RefCount der linken Sequenz. Wenn wir das tun, sehen die Ergebnisse eher so aus.

left |-0-1-2-3-4-5| 
right |---A---B---C| 
result|---1---3---5 
      A B C 

Das Marmor-Diagramm ist, was Sie wollen, wo selectedFileId ist die linke Sequenz und Button ist die richtige Reihenfolge.

13

Verwendung withLatestFrom:

Observable<Integer> selectedFileId= ... 
Observable<MouseClick> buttonClick = ... 

Observable<ProcessFileEvent> processFileEvent = buttonClick.withLatestFrom(selectedFieldId, (b,s) -> { 
    //create ProcessFileEvent here 
}); 

Es nur mit, wenn die ersten ObservablebuttonClick aussendet emittiert.

+0

Dies sollte die Antwort sein, da sie die Frage von OP genau beantwortet –

Verwandte Themen