web-dev-qa-db-fra.com

Comment créer un observable depuis OnClick Event Android?

Je suis nouveau en programmation réactive. J'ai donc un problème lors de la création d'un flux à partir d'un événement, comme onClick, ontouch ...

Quelqu'un peut-il m'aider à résoudre ce problème.

Merci.

35
Thanh Le

Vous feriez quelque chose comme ceci:

Observable<View> clickEventObservable = Observable.create(new Observable.OnSubscribe<View>() {
    @Override
    public void call(final Subscriber<? super View> subscriber) {
        viewIWantToMonitorForClickEvents.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (subscriber.isUnsubscribed()) return;
                subscriber.onNext(v);
            }
        });
    }
});

// You can then apply all sorts of operation here
Subscription subscription = clickEventObservable.flatMap(/*  */);

// Unsubscribe when you're done with it
subscription.unsubscribe();

Puisque vous utilisez Android alors vous pouvez déjà inclure la contrib rxjava-Android dépendance désormais appelée ioreactivex:rxandroid. Ils ont déjà une classe pour faciliter cela. La méthode est ViewObservable.clicks. Vous pouvez l'utiliser comme ça.

Observable<View> buttonObservable = ViewObservable.clicks(initiateButton, false);
    buttonObservable.subscribe(new Action1<View>() {
        @Override
        public void call(View button) {
            // do what you need here
        }
    });

Edit: Depuis la version 1.x, ViewObservable et de nombreuses classes d'assistance sont supprimées de RxAndroid . Vous aurez besoin de bibliothèque RxBinding à la place.

Observable<Void> buttonObservable = RxView.clicks(initiateButton);
    buttonObservable.subscribe(new Action1<Void>() {
        @Override
        public void call(Void x) {
            // do what you need here
        }
    });
51
Miguel Lavigne

Pour Android, jetez un œil à Jake Wharton RxBindings . Par exemple, il vous permet de créer un événement observable et de vous abonner aux événements de clic avec:

RxView.clicks(myButton)
        .subscribe(new Action1<Void>() {
            @Override
            public void call(Void aVoid) {
                /* do something */
            }
        });

ou, mieux encore, avec des expressions lambda (en utilisant soit Kotlin , Java 8 ou Retrolambda ):

RxView.clicks(myButton)
        .subscribe(aVoid -> /* do something */);

Si vous utilisez Kotlin, il convient de noter que RxBindings fournit également fonctions d'extension Kotlin qui vous permettent d'appliquer chaque fonction de liaison directement sur le type cible.

26
Matt

Vous pouvez utiliser un sujet.

Un Subject est une sorte de pont ou de proxy qui agit à la fois comme abonné et comme observable. Parce que c'est un abonné, il peut s'abonner à un ou plusieurs observables, et parce qu'il est observable, il peut passer à travers les éléments qu'il observe en les réémettant, et il peut également émettre de nouveaux éléments.

public class Events {
    public static PublishSubject <Object> myEvent = PublishSubject.create ();
}

Lorsque vous souhaitez publier quelque chose

Events.myEvent.onNext(myObject);

Lorsque vous souhaitez recevoir un événement

Events.myEvent.subscribe (...);

Modifier

** L'utilisation des composants d'architecture LiveData est meilleure car elle gère le cycle de vie et l'activité ou le fragment et vous n'avez pas à vous soucier de vous désabonner des événements car elle observe le cycle de vie des composants ui.

MutableLiveData<Object> event = new MutableLiveData<>();

quand tu veux publier quelque chose

event.postValue(myObject);

Quand vous souhaitez recevoir et événement

event.observe(lifeCycleOwner, (myObject)->...);
16
Roger Garzon Nieto

Utilisation de RxJava 2:

return Observable.create(new ObservableOnSubscribe<View>() {
    @Override
    public void subscribe(ObservableEmitter<View> e) throws Exception {
        clickView.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                e.setCancellable(new Cancellable() {
                    @Override
                    public void cancel() throws Exception {
                        view.setOnClickListener(null);
                    }
                });
                e.onNext(view); // Or whatever type you're observing
            }
        });
    }
});

Semble beaucoup plus agréable en utilisant des lambdas:

return Observable.create(new ObservableOnSubscribe<View>() {
    @Override
    public void subscribe(ObservableEmitter<View> e) throws Exception {
        keypad.setOnClickListener(view -> {
            e.setCancellable(() -> view.setOnClickListener(null));
            e.onNext(view);
        });
    }
});

Ou utilisez simplement RxBinding comme indiqué par d'autres.

Ma solution ci-dessus est un modèle assez général pour envelopper les auditeurs dans un observable.

14
Kavi

Vous pouvez le faire facilement avec Kotlin en utilisant des fonctions d'extension. Par exemple, vous écrivez une fonction d'extension comme celle-ci:

    fun View.observableClickListener(): Observable<View> {
    val publishSubject: PublishSubject<View> = PublishSubject.create()
    this.setOnClickListener { v -> publishSubject.onNext(v) }
    return publishSubject
}

Et vous utiliseriez cette extension comme ceci:

viewIWantToObserveClicks.observableClickListener().subscribe()
0
user3783123