web-dev-qa-db-fra.com

Quelle est la différence entre RxJava 2 annulable et jetable?

Je veux créer un Observable à partir de l'écouteur de clic de vue à l'aide de RxJava 2. J'ai commencé à partir de l'implémentation la plus simple (je n'utilise pas les lambdas ici pour vous montrer différents types dans cette méthode):

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

Ensuite, j'ai réfléchi à la façon de définir onClickListener sur null si ce n'est plus nécessaire. J'ai trouvé qu'il existe deux méthodes avec des noms similaires (comme pour moi):

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

Quelle est la différence entre eux et lequel dois-je utiliser?

21
Gaket

De la Javadoc :

[Cancellable is] Une interface fonctionnelle qui a une seule méthode d'annulation qui peut lancer.

Disposable n'est pas une interface fonctionnelle et lorsque vous implémentez sa méthode dispose(), vous n'êtes pas autorisé à lever des exceptions vérifiées.

En revanche, de nombreux composants non RxJava renvoient un Closeable ou AutoCloseable qui sont définis via throws IOException et throws Exception et sont un peu un fardeau parce que vous auriez besoin de l'essayer.

Par exemple, vous souhaitez utiliser setCancellable lorsque vous travaillez avec un fichier:

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

et vous utiliseriez setDisposable si vous utilisez un Scheduler:

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

    eventSource.onEvent(es ->
        worker.schedule(() -> e.onNext(es))
    );
});
25
akarnokd

Le Cancellable finit par être enveloppé dans un Disposable donc l'effet final est le même pour chaque appel. La différence est que Disposable a plus de fonctionnalités que vous ne voudrez peut-être pas implémenter, donc la simple interface Cancellable est là comme alternative.

Si vous voulez simplement supprimer quelque chose à la fin de l'observable, utilisez Cancellable. Si vous avez une ressource qui peut être supprimée pour une raison externe, vous souhaitez implémenter Disposable pour implémenter la méthode Disposable.isDisposed().

Notez que les méthodes s'excluent mutuellement. Un seul jetable ou annulable peut être enregistré à la fois. L'appel des deux écrase le premier.

14
Kiskae