web-dev-qa-db-fra.com

Comment puis-je créer un observateur sur une liste dynamique dans RxJava?

J'ai besoin de créer un observateur sur un tableau en constante évolution (ajout d'éléments).

J'utilise Obserable.from (Iterable) mais il semble qu'il crée l'Observable sur l'ArrayList tel qu'il est au moment de la création.

J'ai besoin que l'observateur soit averti et que l'action soit exécutée chaque fois que la liste de tableaux obtient un nouvel élément ajouté.

20
juanpavergara

Voilà. Merci à Dávid Karnok sur le groupe Google RxJava

import Java.util.ArrayList;
import Java.util.List;

import rx.Observable;
import rx.subjects.PublishSubject;

public class ObservableListExample {

    public static class ObservableList<T> {

        protected final List<T> list;
        protected final PublishSubject<T> onAdd;

        public ObservableList() {
            this.list = new ArrayList<T>();
            this.onAdd = PublishSubject.create();
        }
        public void add(T value) {
            list.add(value);
            onAdd.onNext(value);
        }
        public Observable<T> getObservable() {
            return onAdd;
        }
    }

    public static void main(String[] args) throws Exception {
        ObservableList<Integer> olist = new ObservableList<>();

        olist.getObservable().subscribe(System.out::println);

        olist.add(1);
        Thread.sleep(1000);
        olist.add(2);
        Thread.sleep(1000);
        olist.add(3);
    }
}
37
juanpavergara

Je considérerais cette approche basée sur BehaviourSubject. Cela diffère de la solution de juanpavergara en ce sens qu'un onNext () sera immédiatement émis vers l'observateur lors de l'abonnement à l'observable.

public class ObservableList<T> {

    protected final List<T> list;
    protected final BehaviorSubject<List<T>> behaviorSubject;

    public ObservableList(List<T> list) {
        this.list = list;
        this.behaviorSubject = BehaviorSubject.create(list);
    }

    public Observable<List<T>> getObservable() {
        return behaviorSubject;
    }

    public void add(T element) {
        list.add(element);
        behaviorSubject.onNext(list);
    }
}


private void main() {
    final List<Integer> list = new ArrayList<>();
    list.add(0);
    list.add(1);

    final ObservableList<Integer> olist = new ObservableList<>(list);

    olist.getObservable().subscribe(System.out::println);

    olist.add(2);
    olist.add(3);
}

Cette solution peut être utile lors de l'implémentation de MVP, lorsque vous souhaitez observer une ressource (c'est-à-dire: une liste d'objets) retournée par un composant du système (c'est-à-dire: un référentiel ou DataSource), et que vous voulez l'Observer (c'est-à-dire: Presenter ou Interactor) pour être averti lorsqu'un élément est ajouté à la liste dans une autre partie du système.

4
GaRRaPeTa

Vous pouvez fusionner deux observables en un seul. L'un d'eux peut être la liste initiale des éléments et le second peut être soumis:

import rx.Observable;
import rx.subjects.ReplaySubject;
import Java.util.ArrayList;
import Java.util.List;

public class ExampleObservableList {
    public static void main(String[] args) {
        List<Integer> initialNumbers = new ArrayList<Integer>();
        initialNumbers.add(1);
        initialNumbers.add(2);

        Observable<Integer> observableInitial = Observable.from(initialNumbers);
        ReplaySubject<Integer> subject = ReplaySubject.create();

        Observable<Integer> source = Observable.merge(observableInitial, subject);

        source.subscribe(System.out::println);

        for (int i = 0; i < 100; ++i) {
            subject.onNext(i);
        }
    }

}

Si vous n'avez pas d'éléments initiaux, vous ne pouvez utiliser que ReplaySubject (ou d'autres Subject -> voir http://reactivex.io/documentation/subject.html ):

public static void main(String[] args) {
    ReplaySubject<Integer> source = ReplaySubject.create();
    source.subscribe(System.out::println);

    for (int i = 0; i < 100; ++i) {
        source.onNext(i);
    }
}
3
krynio