如何将Observable <ontextchangeevent>与Observable <oncheckedchangeevent>?</oncheckedchangeevent> </ontextchangeevent>结合起来

时间:2015-04-13 16:16:41

标签: android rx-java rx-android

我使用RxAndroid库学习RxJava,使用Retrofit进行网络学习,而RetroLambda使用Java8 lambdas。

我想要构建的应用程序具有以下功能:

  • 允许用户键入对Wikipedia API的查询
  • 键入后等待1秒,直到完成网络通话
  • 当应用忙碌时显示进度指示器&#39;获取结果
  • 进度指示器在输入后立即开始,而不是在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,或者#34; en&#34;或&#34; nl&#34;作为维基百科网址的前缀。

GUI before user interacts with it

所以我从Switch创建一个新的Observable,它会发出OnCheckedChangeEvent s。

我的想法是,我需要将此Observable与textStream结合起来。

当切换开关时,基本上应该运行相同的功能,但不完全相同。当前运行的查询(如果在所有运行中)变得过时,因为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

我不能只合并textStreamlanguageSwitchStream

所以问题就变成了:我应该如何处理这个,使用适当的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()添加了{{1}} 切换到Observable,否则它会在发出值之前一直等待它被翻转。

1 个答案:

答案 0 :(得分:1)

使用CombineLatest并执行以下操作:

Observable<SearchParams> uiChangeStream = Observable.combineLatest(
    textStream, 
    languageSwitchStream,
    (text, switch) -> /* extract info from each and return search params */)
.map(searchParams -> wikiService.search(searchParams);
当一个Observable发出新值时,

combineLatest()将从另一个Observable重新发出最后一个值。