如何结合 Observable<OnTextChangeEvent> 和 Observable<OnCheckedChangeEvent>?
How to combine Observable<OnTextChangeEvent> with Observable<OnCheckedChangeEvent>?
我正在使用 RxAndroid 库学习 RxJava,同时使用 Retrofit 进行网络连接,并使用 RetroLambda 使用 Java8 lambdas。
我希望构建的应用具有以下功能:
- 允许用户向维基百科输入查询API
- 键入后等待 1 秒,直到完成网络调用
- 当应用 'busy' 获取结果时显示进度指示器
- 进度指示器在输入后立即开始,而不是 1 秒后,并在收到结果或错误时结束
我是这样工作的:
// emit when text is changed
Observable<OnTextChangeEvent> textStream = WidgetObservable.text(mEditText);
Observable<OnTextChangeEvent> debouncedStream = textStream.debounce(1, TimeUnit.SECONDS); // Unchecked assignment
// start activity indicator immediately
textStream
.observeOn(AndroidSchedulers.mainThread())
.subscribe(s -> mProgressBar.setVisibility(View.VISIBLE));
debouncedStream
.map(t -> wikiService.search(t.text().toString())) // query wikipedia
.map(Object::toString)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(s -> {
mTextView.setText(s == null ? "Error" : s);
mProgressBar.setVisibility(View.GONE);
});
现在,我想添加一个新的小部件,以允许我的维基百科查询使用另一种语言。现在,我将选择一个 Switch,"en" 或 "nl" 作为维基百科 url.
的前缀
所以我从 Switch 创建了一个新的 Observable,它发出 OnCheckedChangeEvent
s。
我的想法是,我需要将这个 Observable 与 textStream
结合起来。
当切换开关时,基本相同的功能应该是 运行,但不完全相同。当前的 运行ning 查询(如果有的话 运行ning)已经过时了,因为 url-prefix 会改变。它应该再等 1 秒钟,然后开始新的网络调用。
显然以下内容不起作用:
// emit when Switch is flipped
Observable<OnCheckedChangeEvent> languageSwitchStream = WidgetObservable.input(mLanguageSwitch);
// emit when text is changed
Observable<OnTextChangeEvent> textStream = WidgetObservable.text(mEditText);
// combine these 2, but they are using different types
Observable uiChangeStream = Observable.merge(textStream, languageSwitchStream);
Observable<OnTextChangeEvent> debouncedStream = uiChangeStream.debounce(1, TimeUnit.SECONDS); // Unchecked assignment
我不能只合并 textStream
和 languageSwitchStream
。
所以问题变成了:我应该如何处理这个问题,使用适当的 Rx?
== 解决方案 ==========================
// emit when Switch is flipped
Observable<OnCheckedChangeEvent> languageSwitchStream =
WidgetObservable
.input(mLanguageSwitch)
.startWith(new OnCheckedChangeEvent() {
@Override
public CompoundButton view() {
return null;
}
@Override
public boolean value() {
return mLanguageSwitch.isChecked();
}
});
// emit when text is changed
Observable<OnTextChangeEvent> textStream = WidgetObservable.text(mEditText);
Observable<OnTextChangeEvent> uiChangeStream = Observable
.combineLatest(
textStream,
languageSwitchStream,
(text, switchValue) -> text);
uiChangeStream
.observeOn(AndroidSchedulers.mainThread())
.subscribe(s -> mProgressBar.setVisibility(View.VISIBLE));
uiChangeStream
.debounce(1, TimeUnit.SECONDS)
.map(t -> wikiService.search(t.text().toString())) // query wikipedia
.map(Object::toString)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(s -> {
mTextView.setText(s == null ? "Error" : s);
mProgressBar.setVisibility(View.GONE);
});
扩展已批准的答案,我添加了 .startsWith()
Switch 的 Observable,否则它会一直等待它被翻转,然后再发出一个值。
使用 CombineLatest 并执行如下操作:
Observable<SearchParams> uiChangeStream = Observable.combineLatest(
textStream,
languageSwitchStream,
(text, switch) -> /* extract info from each and return search params */)
.map(searchParams -> wikiService.search(searchParams);
combineLatest()
将在一个 Observable 发出新值时重新发出另一个 Observable 的最后一个值。
我正在使用 RxAndroid 库学习 RxJava,同时使用 Retrofit 进行网络连接,并使用 RetroLambda 使用 Java8 lambdas。
我希望构建的应用具有以下功能:
- 允许用户向维基百科输入查询API
- 键入后等待 1 秒,直到完成网络调用
- 当应用 'busy' 获取结果时显示进度指示器
- 进度指示器在输入后立即开始,而不是 1 秒后,并在收到结果或错误时结束
我是这样工作的:
// emit when text is changed
Observable<OnTextChangeEvent> textStream = WidgetObservable.text(mEditText);
Observable<OnTextChangeEvent> debouncedStream = textStream.debounce(1, TimeUnit.SECONDS); // Unchecked assignment
// start activity indicator immediately
textStream
.observeOn(AndroidSchedulers.mainThread())
.subscribe(s -> mProgressBar.setVisibility(View.VISIBLE));
debouncedStream
.map(t -> wikiService.search(t.text().toString())) // query wikipedia
.map(Object::toString)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(s -> {
mTextView.setText(s == null ? "Error" : s);
mProgressBar.setVisibility(View.GONE);
});
现在,我想添加一个新的小部件,以允许我的维基百科查询使用另一种语言。现在,我将选择一个 Switch,"en" 或 "nl" 作为维基百科 url.
的前缀所以我从 Switch 创建了一个新的 Observable,它发出 OnCheckedChangeEvent
s。
我的想法是,我需要将这个 Observable 与 textStream
结合起来。
当切换开关时,基本相同的功能应该是 运行,但不完全相同。当前的 运行ning 查询(如果有的话 运行ning)已经过时了,因为 url-prefix 会改变。它应该再等 1 秒钟,然后开始新的网络调用。
显然以下内容不起作用:
// emit when Switch is flipped
Observable<OnCheckedChangeEvent> languageSwitchStream = WidgetObservable.input(mLanguageSwitch);
// emit when text is changed
Observable<OnTextChangeEvent> textStream = WidgetObservable.text(mEditText);
// combine these 2, but they are using different types
Observable uiChangeStream = Observable.merge(textStream, languageSwitchStream);
Observable<OnTextChangeEvent> debouncedStream = uiChangeStream.debounce(1, TimeUnit.SECONDS); // Unchecked assignment
我不能只合并 textStream
和 languageSwitchStream
。
所以问题变成了:我应该如何处理这个问题,使用适当的 Rx?
== 解决方案 ==========================
// emit when Switch is flipped
Observable<OnCheckedChangeEvent> languageSwitchStream =
WidgetObservable
.input(mLanguageSwitch)
.startWith(new OnCheckedChangeEvent() {
@Override
public CompoundButton view() {
return null;
}
@Override
public boolean value() {
return mLanguageSwitch.isChecked();
}
});
// emit when text is changed
Observable<OnTextChangeEvent> textStream = WidgetObservable.text(mEditText);
Observable<OnTextChangeEvent> uiChangeStream = Observable
.combineLatest(
textStream,
languageSwitchStream,
(text, switchValue) -> text);
uiChangeStream
.observeOn(AndroidSchedulers.mainThread())
.subscribe(s -> mProgressBar.setVisibility(View.VISIBLE));
uiChangeStream
.debounce(1, TimeUnit.SECONDS)
.map(t -> wikiService.search(t.text().toString())) // query wikipedia
.map(Object::toString)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(s -> {
mTextView.setText(s == null ? "Error" : s);
mProgressBar.setVisibility(View.GONE);
});
扩展已批准的答案,我添加了 .startsWith()
Switch 的 Observable,否则它会一直等待它被翻转,然后再发出一个值。
使用 CombineLatest 并执行如下操作:
Observable<SearchParams> uiChangeStream = Observable.combineLatest(
textStream,
languageSwitchStream,
(text, switch) -> /* extract info from each and return search params */)
.map(searchParams -> wikiService.search(searchParams);
combineLatest()
将在一个 Observable 发出新值时重新发出另一个 Observable 的最后一个值。