从远程API重用RxJava流

时间:2015-03-26 15:49:54

标签: android rx-java

我有一个API调用,我想使用Observable包装它:

private Observable<RealmResults<Account>> getAccounts() {
        final Observable<RealmResults<Account>> realmAccounts =
                Observable.defer(new Func0<Observable<RealmResults<Account>>>() {
                    @Override
                    public Observable<RealmResults<Account>> call() {
                        return RealmObservable.results(getActivity(), new Func1<Realm, RealmResults<Account>>() {
                            @Override
                            public RealmResults<Account> call(Realm realm) {
                                return realm.where(Account.class).findAll();
                            }
                        });
                    }
                });

        return Observable
                .create(new Observable.OnSubscribe<RealmResults<Account>>() {
                    @Override
                    public void call(final Subscriber<? super RealmResults<Account>> subscriber) {
                        DataBridge.getAccounts(Preferences.getString(Constant.ME_GUID, ""), new OnResponseListener() {
                            @Override
                            public void OnSuccess(Object data) {
                                Log.d("Stream", "onSuccess");
                                realmAccounts.subscribe(subscriber);
                            }

                            @Override
                            public void onFailure(Object data) {
                                subscriber.onError(new Exception(data.toString()));
                            }
                        });
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .startWith(realmAccounts);
    }

我就像

一样使用它
Observable<Accounts> accounts = getAccounts().flatMap(
                new Func1<RealmResults<Account>, Observable<Account>>() {
                    @Override
                    public Observable<Account> call(RealmResults<Account> accounts) {
                        return Observable.from(accounts);
                    }
                });

如何在不调用API的情况下多次使用accounts observable。我需要处理帐户流并从中提取不同的数据集。

1 个答案:

答案 0 :(得分:3)

最简单的方法是使用内部使用cache的运算符ReplaySubject。它缓存源可观察项,然后从缓存中提供结果。

... 
Observable<<RealmResults<Account>> cachedResult = getAccounts().cache();
Observable<Accounts> accountsObservable = cachedResult.flatMap(...);
Observable<X> xObservable = cachedResult.flatMap(...);

如果您想避免缓存结果,则应使用Connectable Observables。通常它只对Hot Observables有用。在调用Connect方法之前,可连接的observable不会开始发出项目。您可以使用publish运算符转换为Connectable Observable。

ConnectableObservable<<RealmResults<Account>> connectebleObservable = getAccounts().publish();
Observable<Accounts> accountsObservable = connectebleObservable .flatMap(...);
Observable<X> xObservable = connectebleObservable .flatMap(...);
//You must subscribe before connect
accountsObservable.subsribe(...);
xObservable.subscribe(...);
//start emiting data
connectebleObservable.connect();

这里重要的一点是你必须在连接之前订阅 - 以避免数据丢失 - 否则你必须使用重播运算符,它类似于缓存运算符,但用于可连接的可观察

那么分享呢?

它创建ConnectableObservable并将其公开为常规Observable。首次订阅会自动导致连接和发射。

在您的情况下使用的共享,无需重播可能会导致数据丢失或多次执行,具体取决于时间。 例如,对于2个订阅者和流中的一个项目,您可能会遇到以下情况:

  1. 在onNext之前创建的2个订阅 - 按预期工作。
  2. 在onNext之后但在onComplete之前创建的第二个订阅 - 第二个订阅仅获取onComplete
  3. 在onComplete之后创建的第二个下标 - 在没有缓存的情况下执行了2次