7

我想在我的 Android 应用程序中进行标准搜索,在其中输入 an EditText,稍等直到用户完成输入,然后使用 Retrofit 启动网络请求:

// make observable out of EditText
Observable<OnTextChangeEvent> textObs = WidgetObservable.text(searchText);

mSearchResultSubscription =
    textObs

        // wait until user has not typed for 350 milliseconds
        .debounce(350, TimeUnit.MILLISECONDS)

        // get the string the user typed
        .map(OnTextChangeEvent::text)
        .map(CharSequence::toString)

        // start a new observable (from Retrofit)
        .flatMap(
            q ->
                // try network call and return my data
                MyRetrofitAPI.getService().search(q)

                    // if this fails, just return empty observable
                    .onErrorResumeNext(error -> {
                        Log.e("Error from retrofit: " + error.getLocalizedMessage());
                        return Observable.empty();
                    })

        )

        // if all is well, show the contents on the screen somehow
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(a -> {
                mAdapter.setItems(a);
            }
            , error -> {
                Log.e("Also error in outer observable: " + error.getLocalizedMessage());
            }
        );

现在,我有一个测试服务器,它接受改造调用并返回一个列表。当我输入“崩溃”时,服务器会执行一些无效代码和错误,返回 http 状态代码 500 和一些错误 html。因此,改造调用失败。

我认为外部 Observable 链不应该受此影响。请参阅我之前的问题:In RxJava, how to retry/resume on error, 而不是完成 observable

但是,外部 Observable 也会出错,导致链终止。错误是: The current thread must have a looper!

奇怪的。现在我尝试不使用.debounce()同样的事情,服务器有一个内部错误,但外部 Observable没有错误。

那么它对.debounce()导致这种行为的线程做了什么?我该如何解决它?

4

2 回答 2

7

添加到pturner 的答案中,调度程序可以作为

.debounce(400, TimeUnit.MILLISECONDS, AndroidSchedulers.mainThread())

这将导致观察者在Android的主线程(UI线程)上工作,并防止观察者抛出错误。

于 2016-06-07T06:26:33.673 回答
2

似乎问题可能与去抖动创建一个新线程来执行代码,来自文档

默认情况下,此变体在计算调度程序上运行,但您可以选择传入您选择的调度程序作为第三个参数。

您可能需要传入一个带有后台 Looper 的 Android 调度程序来解决错误(理论上,不幸的是,如果没有服务器,现在就无法运行您的东西)。

于 2015-07-15T15:41:09.327 回答