2015-07-08 14 views
10

Giả sử tôi có hai Đài quan sát vô hạn có thể phát ra các giá trị tại bất kỳ thời điểm nào. Chúng kết hợp để tạo ra một Observable<ProcessFileEvent>.RxJava- CombineLatest nhưng chỉ cháy cho một phát xạ của Observable?

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

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

Vấn đề là tôi chỉ muốn processFileEvent phát ra khi buttonClick phát ra một cái gì đó, không selectedFileId. Đó chắc chắn không phải là hành vi mà người dùng mong đợi khi ID tệp được nhập và nó khởi động ProcessFileEvent. Làm cách nào để kết hợp nhưng chỉ phát ra khi phát ra buttonClick?

Trả lời

3

Sử dụng .distinctUntilChanged() trên đối tượng MouseClick. Bằng cách đó, bạn sẽ chỉ nhận được sự kiện khi thay đổi MouseClick.

Tạo một lớp có chứa cả fileIdmouseClick:

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

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

Sau đó

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

Điều này có ý nghĩa. Một câu hỏi nhanh. Có 'khác biệt()' dựa vào 'hashcode()/equals()' cho mỗi mục phát ra hay không nó ngăn chặn các chuỗi dupe? – tmn

+1

một HashSet được sử dụng trong nội bộ. Nếu bạn đã thực hiện hashCode()/equals() cho MouseClick thì nó tốt hơn là những gì bạn muốn. Nếu bạn chưa thực hiện chúng thì nó sẽ chỉ sử dụng đối tượng tham chiếu bình đẳng. Oh, đây là overkill tôi chỉ nhận ra chúng ta cần phải sử dụng distinctntntChanged. Tôi sẽ cập nhật. –

+0

Bây giờ, tính năng này không được sử dụng, không có HashSet được tham gia nhưng phương thức equals() được sử dụng để kiểm tra riêng biệt, do đó bạn vẫn cần hàm hashCode()/equals() hoạt động như mong muốn. –

1

Bạn có thể sử dụng Observable.Join để thực hiện việc này. Đặc biệt chú ý đến đoạn này:

Tuy nhiên, những gì tôi có thể làm gì để đảm bảo rằng các cửa sổ không overlap- do đó, một khi một giá trị thứ hai được sản xuất tôi sẽ không còn thấy giá trị đầu tiên? Vâng, nếu chúng tôi trả về chuỗi bên trái từ leftDurationSelector, điều đó có thể thực hiện thủ thuật. Nhưng chờ đợi, khi chúng tôi trả lại chuỗi trái từ leftDurationSelector, nó sẽ thử để tạo đăng ký khác và có thể đưa ra các tác dụng phụ. Câu trả lời nhanh cho điều đó là Xuất bản và RefCount chuỗi bên trái. Nếu chúng tôi làm điều đó, kết quả sẽ trông giống như thế này.

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

Đó sơ đồ bằng đá cẩm thạch là những gì bạn muốn, nơi selectedFileId là dãy bên trái và buttonClick là trình tự đúng.

13

Sử dụng withLatestFrom:

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

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

Nó chỉ phát ra với khi ObservablebuttonClick phát ra đầu tiên.

+0

Đây là câu trả lời chính xác vì câu trả lời cho câu hỏi của OP chính xác –

Các vấn đề liên quan