2016-09-21 13 views
8

Mam dwa obserwable:RxJava scalania debounced i nie debounced obserwable

Obserwowalne O (otwarte): Plik z niektórych treści otwarty w TextView

Obserwowalne E (edit): zawartość pliku edytowane w TextView

Chcę wydobyć E obserwowalne i połączyć go z O obserwowalnym.

obs = Observable.merge(E.debounce(2000, TimeUnit.MILLISECONDS) , O) 
       .subscribe(content->System.out.println("new content: " + content)) 

Problem polega na tym, że jeśli E emituje zdarzenie E1 i zaraz po tym O emituje zdarzenie O1, mamy wyjścia:

new content: O1 
new content: E1 // this output is rebundant (cuz we already have newer content O1) 

To jest schemat tego, co się dzieje: diagram

Jak pozbyć się tego przesadnego starego wydarzenia z wyraźnego obserwowalnego?

+1

Dlaczego nie można przenieść operatora 'debounce' z pracy' merge'? –

+0

@TassosBassoukos, Edytuj wydarzenie (E1) jest bardzo częste (w rzeczywistości jest to wydarzenie wpisane kluczem), więc chcę je odrzucić. Jednak gdy otwieram plik, chcę od razu otrzymać wydarzenie O1 bez usuwania. – wilddev

+1

Możesz używać "wersjonowania" na przykład z czasem. Zamapuj swoje obserwowalne zdarzenia O i obserwowalne E (przed odrzuceniem), aby zawierały zarówno treść, jak i czas. Następnie możesz dokonać porównania, jeśli obserwowane zdarzenie E jest "starsze" niż zdarzenie O obserwowalne. Być może będziesz musiał przejść na Observable.combineLatest o acheive that. – krp

Odpowiedz

2

Można spróbować

Observable.merge(O, O.switchMap(o -> E.debounce())) 
      .subscribe() 

switchMap zachowuje się podobnie jak flatMap, z wyjątkiem, że gdy nowy element jest emitowanego przez źródło obserwowalne, będzie zrezygnować i zatrzymać mirroring obserwowalnym który został wygenerowany z wcześniej emitowanego elementu i rozpoczyna się tylko lustrzane odbicie bieżącego.

2

Widzę dwie główne opcje. Jedną z nich jest użycie znaczników czasowych, które są dość łatwe, ale istnieją teoretyczne warunki wyścigu (ale prawdopodobnie jest to mało prawdopodobne), a drugą opcją jest użycie unikalnego identyfikatora powiązanego z każdym otwarciem pliku, a zdarzenia emitowane z edycji do tekstu tego otwartego pliku są wraz z identyfikatorem otwierania pliku.

Korzystanie timestamps:

obs = Observable.defer(() -> { 
    AtomicBoolean first = new AtomicBoolean(true); 
    e.timestamp() 
    .debounce(2000, TimeUnit.MILLISECONDS)) 
    .mergeWith(o.timestamp()) 
    .buffer(2,1) 
    .flatMap(list -> { 
    Observable<Object> start; 
    if (first.compareAndSet(true, false)) 
     start = Observable.just(list.get(0).getValue()); 
    else 
     start = Observable.empty(); 
    if (list.size() == 1) 
     return start; 
    else { 
     Timestamped<Object> a = list.get(0); 
     Timestamped<Object> b = list.get(1); 
     if (a.getTimestampMillis() <= b.getTimestampMillis()) 
     return start.concatWith(Observable.just(b.getValue())); 
     else 
     return start; 
    } 
    }) 
}); 

Podejrzewam, że wersja o czasie, będą wystarczające.