0

新しい Location を送信できるを返す LocationHandler クラスを作成しようとしていますobservable<Location>。サブスクライバーは最後に追加されたものと後続の値を取得します。

私はこのクラスを書きましたが、それは機能しますが、コールバックを追加したので、それが正しい方法であるかどうかはわかりません。

助けてくれてありがとう。

public class LocationHandler {
    private MessageHandler<Location> onNewItem;
    private Observable<Location> locationObservable;

    public LocationHandler(LocationInitializationBuilder locationInitBuilder) {
        locationObservable = getHookedObservable()
                .mergeWith(locationInitBuilder.build())
                .replay(1).autoConnect();
    }


    private Observable<Location> getHookedObservable() {
        return Observable.create(new ObservableOnSubscribe<Location>() {
            @Override
            public void subscribe(ObservableEmitter<Location> e) throws Exception {
                onNewItem = location -> e.onNext(location);
            }
        });
    }

    public Observable<Location> getLocation(){
        return locationObservable;
    }

    public void setLocation(Location address){ // <---------- add new values
        if (onNewItem != null){
            onNewItem.handleMessage(address);
        } else {
            throw new IllegalStateException("Cannot add an item to a never subscribed stream");
        }
    }
}

@Blackbelt のアドバイスに従って、ReplaySubject で変更しました。

public class LocationHandler {
    private ReplaySubject<Location> inputStream = ReplaySubject.create(1);
    private Observable<Location> locationObservable;

    public LocationHandler(LocationInitializationBuilder locationInitBuilder) {
        locationObservable = locationInitBuilder.build()
                .mergeWith(inputStream)
                .replay(1).autoConnect();
    }

    public Observable<Location> getLocation(){
        return locationObservable;
    }

    public void setLocation(Location address){
        inputStream.onNext(address);
    }
}
4

2 に答える 2

3

の代わりに件名を使用できますMessageHandler。サブジェクトは、オブザーバブルおよびサブスクライバーとして同時に機能できます。サブスクライブするメソッドLocationHandlerを返すSubject#asObservableことができます。内部的には、場所を指定setLocationして呼び出す必要がありSubject#onNextます。さまざまなタイプのサブジェクトが利用可能です。ドキュメントを参照して、ニーズにより適したものを選択してください。例えば

  public class LocationHandler {
     BehaviorSubject<GeevLocation> mLocationSubject = BehaviorSubject.create();

     public Observable<GeevLocation> getLocation() {
        return mLocationSubject.asObservable();
     }

    public void setLocation(GeevLocation address){
        mLocationSubject.onNext(address);
    }
 }

外部呼び出しgetLocationから、返された を購読しObservableます。asetLocationが呼び出されると、オブジェクトを取得しますonNext

于 2016-11-08T16:13:07.697 に答える
1

Blackbelt がすでに言ったように、Subject を使用します。特に、BehaviorSubject を使用します。サブジェクトはデフォルトでホットですが、サブスクリプションによってイベントをリプレイできます。サブスクライブすると、BehaviorSubject は最後に発行された値または初期値を提供します。すべてのサブスクライバーは、入ってくると値を取得します。ストリームはホットであるため、決して終了しません。2 番目の onError が飲み込まれてしまうため、エラー処理を覚えておいてください。

サンプルコード

class Location {

}

class LocationInitializationBuilder {
    static Location build() {
        return new Location();
    }
}

class LocationHandler {
    private Subject<Location> locationObservable;

    public LocationHandler(LocationInitializationBuilder locationInitBuilder) {
        Location initialValue = LocationInitializationBuilder.build();

        locationObservable = BehaviorSubject.<Location>createDefault(initialValue).toSerialized();
    }

    public Observable<Location> getLocation() {
        return locationObservable.hide();
    }

    public void setLocation(Location address) { // <---------- add new values
        locationObservable.onNext(address);
    }
}

public class LocationTest {
    @Test
    public void name() throws Exception {
        LocationHandler locationHandler = new LocationHandler(new LocationInitializationBuilder());

        TestObserver<Location> test = locationHandler.getLocation().test();

        locationHandler.setLocation(new Location());

        test.assertValueCount(2);
    }
}
于 2016-11-08T17:28:33.817 に答える