2017-04-07 14 views
8

Tôi muốn tạo ra một Observable khỏi tầm nhìn nhấp chuột nghe sử dụng RxJava 2. Tôi bắt đầu từ việc thực hiện đơn giản nhất (tôi không sử dụng lambdas đây để hiển thị cho bạn các loại khác nhau trong phương pháp này):Sự khác nhau giữa RxJava 2 Cancellable và Disposable là gì?

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); 
        } 
       } 
      }); 
     } 
    }); 

Sau đó, tôi nghĩ về cách đặt onClickListener thành null nếu không cần thêm. Tôi thấy rằng có hai phương pháp với tương tự (như đối với tôi) tên:

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

sự khác biệt giữa họ và mà tôi nên sử dụng là gì?

Trả lời

14

Từ Javadoc:

[Cancellable là] Một giao diện chức năng mà có một đơn hủy bỏ phương pháp mà có thể ném.

Disposable không phải là giao diện chức năng cộng với khi triển khai phương thức dispose(), bạn không được phép ném ngoại lệ đã kiểm tra.

Ngược lại, nhiều thành phần không phải RxJava trả lại Closeable hoặc AutoCloseable được xác định qua throws IOExceptionthrows Exception và có phần gánh nặng vì bạn cần thử bắt.

Ví dụ, bạn muốn sử dụng setCancellable khi bạn làm việc với một tập tin:

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(); 
}); 

và bạn muốn sử dụng setDisposable nếu bạn sử dụng một Scheduler:

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

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

Cảm ơn bạn. Tôi có nên sử dụng 'check if (! E.isDisposed())' nếu tôi sử dụng Cancellable và không được Disposed? – Gaket

+0

Có, cuộc gọi xử lý xuôi dòng được phản ánh đúng thông qua isDisposed() bất kể bạn có tài nguyên gì. – akarnokd

+1

Đối với trường hợp cơ bản này, bạn không thực sự cần nó, nhưng trong trường hợp bạn muốn phát ra 'onError', bạn nên kiểm tra isDisposed() vì nếu bộ phát được xử lý, lỗi sẽ được chuyển đến lỗi toàn cầu trình xử lý đổ vỡ ứng dụng Android thường bất ngờ. – akarnokd

6

Cancellable kết thúc bằng việc được gói gọn thành Disposable để hiệu quả cuối cùng giống nhau đối với cả hai cuộc gọi. Sự khác biệt là Disposable có nhiều tính năng hơn mà bạn có thể không muốn triển khai, do đó, giao diện Cancellable đơn giản có sẵn thay thế.

Nếu bạn chỉ muốn vứt bỏ thứ gì đó khi quan sát kết thúc, hãy sử dụng Cancellable. Nếu bạn có tài nguyên có thể bị xử lý vì một số lý do bên ngoài bạn muốn triển khai Disposable để triển khai phương thức Disposable.isDisposed().

Lưu ý rằng các phương pháp loại trừ lẫn nhau. Chỉ một lần dùng một lần hoặc có thể hủy có thể được đăng ký cùng một lúc. Gọi cả hai ghi đè lên đầu tiên.

+0

Cảm ơn bạn. Tôi có nên sử dụng kiểm tra 'if (! E.isDisposed())' nếu tôi sử dụng Cancellable và không được xử lý? – Gaket

+0

akarnokd là một trong những nhà phát triển RxJava và ví dụ của anh ta không sử dụng nó để kiểm tra xem có lẽ không cần thiết. Theo như tôi biết kiểm tra như vậy chỉ được yêu cầu trên các cuộc gọi 'onError' vì một lỗi trên một quan sát được xử lý sẽ đi đến xử lý ngoại lệ toàn cầu. – Kiskae

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