有没有更清洁的方法来执行以下操作?
我有一个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);
答案 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的一部分 - 您可以在这里查看源代码:
它只是一个简单的POJO,它包含对已更改的EditText的引用以及 EditText的当前内容。后者是我在flatMap
中使用的。