Получите последнее значение Наблюдаемого и немедленно испустите его

Я пытаюсь получить последнее значение данного 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. Я не знаю, возможна ли вообще такая вещь. Кто-нибудь знает, как достичь этой цели? Спасибо вам

Ответ 1

last() метод не будет здесь полезен, так как он ждет завершения Observable, чтобы дать вам последний элемент, испущенный.

Предполагая, что у вас нет контроля над излучающим наблюдаемым, вы можете просто создать BehaviorSubject и подписать его наблюдаемому, который испускает данные, которые вы хотите прослушать, а затем подписаться на созданный объект. Поскольку Subject - это Observable и Subscriber, вы получите то, что хотите.

Я думаю (у меня нет времени проверить его сейчас), вам, возможно, придется вручную отказаться от подписки от оригинала, наблюдаемого как 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

Ответ 2

В RxJava, подписчик .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 предпочитает вам выполнять асинхронную работу.

Ответ 3

То, что вы на самом деле хотите достичь здесь, - это взять асинхронную задачу и преобразовать ее в синхронную.

Существует несколько способов достижения этого, каждый из которых имеет плюсы и минусы:

  • Используйте toBlocking() - это означает, что этот поток будет BLOCKED, пока поток не закончится, чтобы получить только один элемент просто используйте first(), поскольку он будет завершен после доставки предмета. пусть весь ваш поток Observable<T> getData(); то метод, который сразу получит последнее значение, будет выглядеть следующим образом:

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

пожалуйста, не используйте last(), так как он будет ждать завершения потока и только затем испустит последний элемент.

Если ваш поток является сетевым запросом, и он еще не получил какой-либо элемент, это заблокирует ваш поток!, поэтому используйте его только в том случае, если вы уверены, что есть доступный предмет немедленно (или если вы действительно хотите блок...)

  • другой вариант заключается в том, чтобы просто кэшировать последний результат, что-то вроде этого:

    getData(). subscribe (t- > cachedT = t;)//где-то в коде, и он сохранит сохраненный последний отправленный товар public T getLastItem() {   return cachedT; }

если к моменту вашего запроса не было отправлено ни одного элемента, вы получите нулевое или какое-либо начальное значение, которое вы установили. проблема с этим утверждением заключается в том, что фаза подписки может произойти после get и может сделать условие гонки, если используется в двух разных потоках.