web-dev-qa-db-ja.com

Observableの最新の値を取得し、すぐに送信します

私は与えられた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

これを行うと、flatMapmyObservable1を発行するため、mapに到達するために発行する必要があります。そのようなことをすることが可能かどうかはわかりません。誰もこの目標を達成する方法について何か手がかりを持っていますか?ありがとうございました

12
E-Kami

last()メソッドは、Observableが終了して最後に発行されたアイテムを取得するのを待つため、ここでは役に立ちません。

放出するオブザーバブルを制御できないと仮定すると、単にBehaviorSubjectを作成し、それをリッスンしたいデータを放出するオブザーバブルにサブスクライブし、作成したサブジェクトをサブスクライブできます。 SubjectObservableSubscriberの両方であるため、必要なものが得られます。

彼の購読者がすべて自動的に購読解除しないと、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

23
MatBos

RxJavaでは、subscriber.onXXXは非同期と呼ばれます。つまり、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
dieyidezui

ここで実際に達成したいのは、非同期タスクを取得して同期タスクに変換することです。

それを達成するにはいくつかの方法があり、それぞれ長所と短所があります:

  • toBlocking() を使用します。これは、ストリームが終了するまでこのスレッドがブロックされることを意味し、1つのアイテムのみを取得するには、単に first() を使用します。アイテムが配信されたら。ストリーム全体がObservable<T> getData();であるとすると、最後の値をすぐに取得するメソッドは次のようになります。

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

last() は使用しないでください。ストリームが完了するのを待ってから、最後のアイテムを出力するだけです。

ストリームがネットワーク要求であり、まだアイテムを取得していない場合、これはスレッドをブロックします!したがって、すぐに使用可能なアイテムがあることが確実な場合にのみ使用してください(またはブロックが本当に必要な場合...)

  • 別のオプションは、次のような最後の結果を単にキャッシュすることです:

    getData()。subscribe(t-> cachedT = t;)//コード内のどこかに、配信された最後のアイテムを保存し続けますpublic T getLastItem(){return cachedT; }

要求した時点でアイテムが送信されなかった場合、nullまたは設定した初期値が取得されます。このアプローチの問題は、サブスクライブ段階がgetの後に発生し、2つの異なるスレッドで使用されると競合状態になる可能性があることです。

0
ndori