获取Observable的最新值并立即发出

时间:2016-05-03 16:13:30

标签: java rx-java reactive-programming rx-android

我试图获取给定Observable的最新值并让它发出 一旦被召唤就立刻。以下面的代码为例:

return Observable.just(myObservable.last())
    .flatMap(myObservable1 -> {
        return myObservable1;
    })
    .map(o -> o.x) // Here I want to end up with a T object instead of Observable<T> object

这不起作用,因为通过这样做,flatMap将会发出myObservable1,而map将会发出.edcar_letter{ font-size:180px; } @media screen and (max-width: 350px) { .edcar_letter{ font-size:120px; } } 发射以到达var uris = ['/test.xml', '/test2.xml']; var counts = []; for (var p of xdmp.documentProperties(uris)) { counts.push(fn.count(p.xpath('//data'))) } counts 。 我不知道是否可以做这样的事情。有没有人知道如何实现这一目标?谢谢

3 个答案:

答案 0 :(得分:23)

last()方法在这里没有任何帮助,因为它等待Observable终止以给你最后一个项目。

假设您无法控制发射的observable,您可以简单地创建一个BehaviorSubject并将其订阅到发出您想要侦听的数据的observable,然后订阅创建的主题。由于Subject同时是ObservableSubscriber,您将获得所需内容。

我认为(现在没有时间检查)您可能必须手动取消订阅原始观察资料BehaviorSubject一旦所有订阅者取消订阅都不会自动取消订阅。

这样的事情:

BehaviorSubject subject = new BehaviorSubject();
hotObservable.subscribe(subject);
subject.subscribe(thing -> {
    // Here just after subscribing 
    // you will receive the last emitted item, if there was any.
    // You can also always supply the first item to the behavior subject
});

http://reactivex.io/RxJava/javadoc/rx/subjects/BehaviorSubject.html

答案 1 :(得分:2)

在RxJava中,subscriber.onXXX被称为异步。这意味着如果您的Observable在新线程中发出项目,则在返回之前永远不能获取最后一项,除非您阻止该线程并等待该项目。但是如果Observable同步发出项目,你不要通过subscribeOn和observOn改变它的线程, 比如代码:

Observable.just(1,2,3).subscribe();

在这种情况下,你可以这样做:

Integer getLast(Observable<Integer> o){
    final int[] ret = new int[1];
    Observable.last().subscribe(i -> ret[0] = i);
    return ret[0];
}

这样做是个坏主意.RxJava更喜欢你做异步工作。

答案 2 :(得分:0)

您实际想要实现的是接受异步任务并将其转换为同步任务。

有几种方法可以实现它,每种方法都有它的优点和缺点:

  • 使用toBlocking() - 这意味着此流程将被阻止,直到流完成为止,只有一个项目只需使用first(),因为它将在项目交付后完成。 假设您的整个流都是Observable<T> getData(); 那么立即得到最后一个值的方法将如下所示:

public T getLastItem(){ return getData().toBlocking().first(); }

请不要使用last(),因为它会等待流完成,然后才会发出最后一项。

如果你的流是一个网络请求并且它没有得到任何项目,那么这将阻止你的线程!所以只有当你确定有一个项目可以立即使用它时(或者如果你真的想要一个块)。 ..)

  • 另一种选择是简单地缓存最后的结果,如下所示:

    getData()。subscribe(t-&gt; cachedT = t;)//在代码中的某个地方,它将继续保存最后交付的项目 public T getLastItem(){     return cachedT; }

如果您在请求时没有发送任何项目,您将获得null或您设置的任何初始值。 这个approch的问题是订阅阶段可能在get之后发生,如果在2个不同的线程中使用,可能会产生竞争条件。