簡體   English   中英

RxJava- CombineLatest 但僅針對一個 Observable 的發射觸發?

[英]RxJava- CombineLatest but only fire for one Observable's emission?

假設我有兩個可以隨時發出值的無限 Observable。 它們結合起來創建一個Observable<ProcessFileEvent>

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

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

問題是我只希望 processFileEvent 在buttonClick發出某些東西時發出,而不是selectedFileId 當輸入文件 ID 並啟動ProcessFileEvent時,這絕對不是用戶期望的行為。 如何組合但僅在buttonClick發出時發出?

使用withLatestFrom

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

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

它僅在第一個Observable buttonClick發出時發出。

使用.distinctUntilChanged()上的MouseClick的對象。 這樣,您只會在MouseClick更改時獲取事件。

創建一個包含fileIdmouseClick

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

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

然后

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

您可以使用Observable.Join執行此操作。 特別注意這一段:

但是,我該怎么做才能確保這些窗口不重疊 - 這樣,一旦產生第二個值,我將不再看到第一個值? 好吧,如果我們從leftDurationSelector返回左側序列,那就可以了。 但是等等,當我們從leftDurationSelector返回序列時,它會嘗試創建另一個訂閱,這可能會引入副作用。 快速回答是發布和RefCount左側序列。 如果我們這樣做,結果看起來更像這樣。

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

那個大理石圖是你想要的,其中selectedFileId是左序列,buttonClick是正確的序列。

這對我有用,缺少的部分是startWith()運算符。 一旦你將它添加到可觀察對象中,它就會開始工作。

樣本

         Observable.combineLatest(
                    firstObservable.observeDoors("1").startWith(emptyList<Door>()),
                    secondObservable.observeUnits("2").startWith( emptyList<Door>())
                ) { doors, units ->
                    ArrayList<Door>().apply {
                        addAll(units)
                        addAll(doors)
                    }
                }.map { 
                    //do something 
                }

這是因為 combine 需要所有源開始發出至少一個值,它會初始化 stream,然后只聽它的變化。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM