2017-04-07 8 views
8

Chcę utworzyć Observable z Kliknięciem słuchacza z wykorzystaniem RxJava 2. zacząłem od najprostszej realizacji (nie używam lambdy tutaj, aby pokazać różne typy w tej metodzie):Jaka jest różnica między RxJava 2 usuwalny i jednorazowy?

Observable<View> viewObservable = Observable.create(new ObservableOnSubscribe<View>() { 
     @Override 
     public void subscribe(@NonNull ObservableEmitter<View> e) throws Exception { 
      mNewWordView.setOnClickListener(new View.OnClickListener() { 
       @Override 
       public void onClick(View value) { 
        if (!e.isDisposed()) { 
         e.onNext(value); 
        } 
       } 
      }); 
     } 
    }); 

potem pomyślałem o tym, jak ustawić onClickListener na wartość null, jeśli nie jest potrzebna dalej. Okazało się, że istnieją dwie metody z podobnych (jak dla mnie) nazwami:

e.setCancellable(Cancellable c); i e.setDisposable(Disposable d);

Jaka jest różnica między nimi a które należy używać?

Odpowiedz

14

Z Javadoc:

[Cancellable jest] funkcjonalny interfejs ma sposobu pojedynczy unieważnienia, który może wyrzucić.

Disposable nie jest funkcjonalny interfejs oraz przy wdrażaniu jego metodę dispose(), nie wolno rzucać sprawdzonych wyjątków.

Natomiast wiele elementów non-RxJava zwróci Closeable lub AutoCloseable które są zdefiniowane poprzez throws IOException i throws Exception i są nieco uciążliwe, ponieważ należałoby spróbować-go złapać.

Na przykład, że chcesz użyć setCancellable podczas pracy z plikiem:

Observable.create((ObservableEmitter<byte[]> e) -> { 
    FileInputStream fin = new FileInputStream("raw.dat"); 
    e.setCancellable(fin::close); 

    byte[] buffer = new byte[4096]; 

    for (;;) { 
     int r = fin.read(buffer); 
     if (r < 0) { 
      break; 
     } 
     e.onNext(buffer); 
    } 
    e.onComplete(); 
}); 

i chcesz używać setDisposable jeśli używasz Scheduler:

Observable.create((ObservableEmitter<Event> e) -> { 
    Worker worker = Schedulers.io().createWorker(); 
    e.setDisposable(worker); 

    eventSource.onEvent(es -> 
     worker.schedule(() -> e.onNext(es)) 
    ); 
}); 
+0

Dziękuję. Czy powinienem użyć 'check if (! E.isDisposed()) jeśli używam Cancellable i Disposed? – Gaket

+0

Tak, wywołanie upakowania w dalszym ciągu jest poprawnie odzwierciedlane przez isDisposed() bez względu na posiadane zasoby. – akarnokd

+1

W tym podstawowym przypadku naprawdę nie jest to potrzebne, ale na wypadek, gdybyś chciał emitować 'onError', zaleca się kontrolę isDisposed(), ponieważ jeśli emiter zostanie usunięty, błąd zostanie skierowany do globalnego błędu program obsługi, który często nieoczekiwanie powoduje awarię aplikacji na Androida. – akarnokd

6

The Cancellable kończy się pakowanie w Disposable, więc efekt końcowy jest taki sam dla każdego połączenia. Różnica polega na tym, że Disposable ma więcej funkcji, których możesz nie chcieć implementować, więc prosty interfejs Cancellable jest dostępny jako alternatywa.

Jeśli chcesz tylko pozbyć się czegoś, gdy obserwowalne końce używają Cancellable. Jeśli masz zasób, który może zostać usunięty z powodu jakiegoś zewnętrznego powodu, dla którego chcesz zaimplementować metodę Disposable w celu wdrożenia metody Disposable.isDisposed().

Należy zauważyć, że metody wzajemnie się wykluczają. Jednorazowo można zarejestrować tylko jedno jednorazowe lub odwołalne. Wywołanie obu powoduje nadpisanie pierwszego.

+0

Dziękuję. Czy powinienem użyć polecenia 'if (! E.isDisposed())' jeśli używam anulowania i nie usunięto? – Gaket

+0

akarnokd jest jednym z programistów RxJava, a jego przykład go nie używa, więc sprawdź czy prawdopodobnie nie jest to wymagane. O ile mi wiadomo taka kontrola jest wymagana tylko w wywołaniach 'onError', ponieważ błąd w usuwanym obserwowalnym przejdzie do globalnej procedury obsługi wyjątku. – Kiskae

Powiązane problemy