onNext启动另一个Observable

时间:2014-10-14 20:53:30

标签: android rx-java

有没有更清洁的方法来执行以下操作?

我有一个Android observable可以去除请求。 onNext它调用第二个observable。

{// when creating the android activity
searchTextEmitterSubject = PublishSubject.create();
subscription = AndroidObservable.bindActivity(this, Observable.switchOnNext(searchTextEmitterSubject))
                .debounce(100, TimeUnit.MILLISECONDS, Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<String>() {
                    @Override
                    public void onCompleted() {
                    }

                    @Override
                    public void onError(Throwable e) {
                    }

                    @Override
                    public void onNext(String s) {
                        Log.d("a",s);
                        pa.doSearch(s);
                    }
                });
}

@OnTextChanged(R.id.ed)
public void onTextEntered(CharSequence charsEntered) {
    searchTextEmitterSubject.onNext(getASearchObservableFor(charsEntered.toString()));
}


private Observable<String> getASearchObservableFor(final String searchText) {
    return Observable.create( (Subscriber<? super String> subscriber) ->
            subscriber.onNext(searchText)).subscribeOn(Schedulers.io());
}

doSearch实例化第二个observable:

public void doSearch(String string) {
    AlbumEndpoint albumEndpoint = API.getRestAdapter().create(AlbumEndpoint.class);
    Observable<Point> observable = albumEndpoint.searchPoint(string);
    mAdapterDataSubscription = AndroidObservable.bindActivity((Activity) getContext(), observable)
            .subscribe(mAdapterDataObserver);

}

private Observer<Point> mAdapterDataObserver = new Observer<Point>() {

    @Override
    public void onCompleted() {
        mAdapterDataSubscription.unsubscribe();
    }

    @Override
    public void onError(Throwable e) {
        e.printStackTrace();
    }

    @Override
    public void onNext(Point point) {
        List<Point.Result> results = point.getResults();
        mData.addAll(results);
        notifyDataSetChanged();
    }

};

有效。但有没有办法合并&#34;这两个流可以提高可读性还是创建最佳代码?


编辑:为了完整起见以及任何对未来感兴趣的人,我设法将代码缩小为:

Observable<EditText> searchTextObservable = ViewObservable.text(ed);
searchTextObservable.debounce(100, TimeUnit.MILLISECONDS)
        .flatMap(editText -> {
            String string = editText.getText().toString();
            AlbumEndpoint albumEndpoint = getRestAdapter().create(AlbumEndpoint.class);
            return albumEndpoint.searchPoint(string);
        })
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(mAdapterDataObserver);

1 个答案:

答案 0 :(得分:2)

有几件事:

我不确定,为什么每次都将文本更改事件包装到新的Observable中,而不是立即将它们传递给您的主题:

所以,而不是:

@OnTextChanged(R.id.ed)
public void onTextEntered(CharSequence charsEntered) {
    searchTextEmitterSubject.onNext(getASearchObservableFor(charsEntered.toString()));
}

试试这个:

@OnTextChanged(R.id.ed)
public void onTextEntered(CharSequence charsEntered) {
    searchTextSubject.onNext(charsEntered.toString());
}

当然,您将拥有PublishSubject<String>而不是PublishSubject<Observable<String>>

但是你可以跳过onNextSwitch而只是debounce你的主题并从那里继续。

为了进一步简化,您可以使用rxjava Android软件包中的ViewObservables。我最近没有使用它们,但它应该像这样工作:

Observable<OnTextChangeEvent> searchTextObservable = ViewObservable.text(tvSearch);

每次调用基础TextWatcher OnTextChangeEvent时都会发出afterTextChanged(默认情况下,在ButterKnife中使用onTextChanged,这可能是一个微妙的差)。

如果我错过了在Observable中包装每个文本更改的一些重要原因,这也可以通过更简单的方式实现:

@OnTextChanged(R.id.ed)
public void onTextEntered(CharSequence charsEntered) {
    searchTextEmitterSubject.onNext(
        Observable.just(charsEntered.toString())
    );
}

请注意,我也省略了subscribeOn(Schedulers.io()) - 我从未觉得需要将事件侦听器从UI线程移动到其他线程。我在这里错过了什么吗?

最后,你可以使用flatMap来实际执行每个搜索字词的搜索(我在这里使用自己的Observable<OnTextChangeEvent>):

searchTextObservable
.debounce(100, TimeUnit.MILLISECONDS)
.flatMap(new Func1<OnTextChangeEvent, Observable<Point>>() {

    @Override
    public Observable<Point> call(OnTextChangeEvent event) {
        final String string = event.text.toString();
        AlbumEndpoint albumEndpoint = API.getRestAdapter().create(AlbumEndpoint.class);
        Observable<Point> pointObservable = albumEndpoint.searchPoint(string);
        return AndroidObservable.bindActivity((Activity) getContext(), pointObservable);
    }

})
.observeOn(AndroidSchedulers.mainThread())
.subscribe(mAdapterDataObserver);

如果albumEndpoint尚未执行此操作,您可能需要将pointObservable移动到IO线程。

我希望这有帮助!

编辑:抱歉,我忘了解释OnTextChangeEvent是什么。这是rx-android的一部分 - 您可以在这里查看源代码:

https://github.com/ReactiveX/RxAndroid/blob/0.x/src/main/java/rx/android/events/OnTextChangeEvent.java

它只是一个简单的POJO,它包含对已更改的EditText的引用以及 EditText的当前内容。后者是我在flatMap中使用的。