如何在onError()/ unsubscribing之前继续观察对象

时间:2015-06-01 23:02:05

标签: java asynchronous reactive-programming rx-java observable

我需要观察一个对象列表,并在列表中有新对象时立即发出事件。像客户端 - 服务器应用程序一样,客户端将内容添加到列表中,服务器将新添加的内容发送到服务器中注册的所有客户端。

到目前为止,我的observable只发出一个项目而不是它之后。换句话说,当一个新对象被添加到列表中时,会有一个事件,但是当添加第二个(或第3个,第4个,第5个......)对象时,没有事件。

我需要它在列表中有新对象时继续发出项目。

这是我的代码,其中MyList让我自己实现List(与我的问题无关)。我希望发出的事件是MyList新添加的对象。

private void onClickMethod() {
    MyList myList = populateMyList();

    onNexAction = new Action1<MyList>() {
        @Override
        public void call(MyList myList) {
            System.out.println("call()");
            TheObject theObject = myList.getNext();
            System.out.println("New Event: " + theObject.getData());
        }
    };

    myObservable = Observable.create(new Observable.OnSubscribe<MyList>() {
        @Override
        public void call(Subscriber<? super MyList> t) {
            t.onNext(myList);
        }
    });

    myObservable.observeOn(Schedulers.newThread()).subscribeOn(Schedulers.io()).subscribe(onNexAction);
}

上面的代码只会发出第一个添加的对象。但是如果我在call()中放置一个while循环,它将发出所有事件,就像我想要的那样。但我觉得不适合做我想做的事。我觉得我更像是轮询而不是异步。

以下是完全相同的代码,但是使用while循环:

private void onClickMethod() {
    MyList myList = populateMyList();

    onNexAction = new Action1<MyList>() {
        @Override
        public void call(MyList myList) {
            System.out.println("call()");
            while (myList.size() > 0) { // The while cycle
                TheObject theObject = myList.getNext();
                System.out.println("New Event: " + theObject.getData());
            }
        }
    };

    myObservable = Observable.create(new Observable.OnSubscribe<MyList>() {
        @Override
        public void call(Subscriber<? super MyList> t) {
            t.onNext(myList);
        }
    });

    myObservable.observeOn(Schedulers.newThread()).subscribeOn(Schedulers.io()).subscribe(onNexAction);
}

那么,我在这里做错了什么?如果MyList中有新对象,我怎样才能让我的observable发出新事件?

编辑:

根据Tassos Bassoukos的建议,我像这样应用了distinct()运算符:

myObservable.observeOn(Schedulers.newThread()).subscribeOn(Schedulers.io()).distinct().subscribe(onNexAction);

但它并没有解决我的问题。只发出第一个添加的对象。

3 个答案:

答案 0 :(得分:5)

这是PublishSubject的典型案例:

class MyList<T> {
    final PublishSubject<T> onAdded = PublishSubject.create();
    void add(T value) {
        // add internally
        onAdded.onNext(value);
    }
    Observable<T> onAdded() {
        return onAdded;
    }
}

MyList<Integer> list = populate();

Subscription s = list.onAdded()
    .subscribe(v -> System.out.println("Added: " + v));

list.add(1);  // prints "Added: 1"
list.add(2);  // prints "Added: 2"
list.add(3);  // prints "Added: 3"

s.unsubscribe(); // not interested anymore

list.add(4);  // doesn't print anything
list.add(5);  // doesn't print anything

答案 1 :(得分:0)

根据您的代码,当用户点击(某事物)时,会调用<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.6</version> </dependency>

此方法将创建一个对象onClickMethod,您将构建一个将发出此对象的项目。然后你将使用这个对象。

事实上,你只会发出一次你的名单,这就是为什么你只通知一次(只需点击一下)

要实现您的目标,一种可能的方法是在添加列表时发出列表中的每个项目。

myList

}

请注意,此代码 NOT 效果良好,因为它会循环遍历private void onClickMethod() { MyList myList = populateMyList(); myObservable = Observable.create(subscriber -> { int currentSize = myList.size(); while(myList.size() != currentSize) { subscriber.onNext(myList.getNext()); currentSize = myList.size(); } subscriber.onCompleted(); }); myObservable.observeOn(Schedulers.newThread()) .subscribeOn(Schedulers.io()) .subscribe(item -> System.out.println(item)); ,如果有人在循环代码中添加/删除项目,则可能会遇到问题。

更好的方法是在myList.size()中添加新项目时收到通知,然后发出此新项目。

答案 2 :(得分:0)

首先,你没有从observable获得多个值的原因是你传递给Observable.create的方法只被称为一次,并且它在第一次出现时订阅。如果您想将列表作为可观察对象进行连接,最简单的方法是MyList类实现Iterable,您可以直接使用from

private void onClickMethod() {
 MyList myList = populateMyList();
 Observable.from(myList)
           .observeOn(Schedulers.newThread())
           .subscribe(item -> System.out.println(item));

}