对EditText进行改造+取消会导致InterruptedIOException

时间:2018-11-09 19:19:06

标签: android retrofit rx-java2

我目前有一个EditText供用户输入搜索内容。我正在尝试将RxJava与debounce一起使用,以便经常搜索,而不是每个字符。但是,我在进行测试时得到InterruptedIOException,这会杀死流。

private val subject = BehaviorSubject.create<String>()

init {
    configureAutoComplete()
}

private fun configureAutoComplete() {
    subject.debounce(200, TimeUnit.MILLISECONDS)
        .flatMap {
            getSearchResults(query = it)
        }
        .subscribe({ result ->
            handleResult(result)
        }, { t: Throwable? ->
            Logger.e(t, "Failed to search")
        })
}

fun getSearchResults(query: String): Observable<List<MyObject>> {
    val service = NetworkService.create() // get retrofit service
    return service.search(query)
}


fun search(text: String) {
    subject.onNext(text)
}

如您所见,我正在创建一个BehaviorSubject,并在init中使用debounce进行设置。

getSearchResult返回一个Observable并执行我的网络请求。

但是在测试过程中,如果我以特定的速率键入(通常是快速启动,例如在请求进行过程中键入另一个字符),则会抛出Exception

 Failed to search : java.io.InterruptedIOException
    at okhttp3.internal.http2.Http2Stream.waitForIo(Http2Stream.java:579)
    at okhttp3.internal.http2.Http2Stream.takeResponseHeaders(Http2Stream.java:143)
    at okhttp3.internal.http2.Http2Codec.readResponseHeaders(Http2Codec.java:125)

我正在看https://stackoverflow.com/a/47276430/3106174,看来我做得正确。

1 个答案:

答案 0 :(得分:0)

经过更多测试之后,我意识到网络请求位于主线程上。

您可以通过以下方式进行测试:用Observerable.create{ ... }代替网络通话,并在其中扔出Thread.sleep(1000)

我正在关注本教程https://proandroiddev.com/building-an-autocompleting-edittext-using-rxjava-f69c5c3f5a40,其中一条评论提到了此问题。

  

“但是我认为您的代码段中有误导之处,这是   主题不是线程安全的。还有您的代码将要执行的线程   运行将是您发出的线程(在这种情况下,主线程   线)。 “

要解决此问题,您需要强制其在Schedulers.io()上运行。确保它在debounce之后,否则将不起作用。

private fun configureAutoComplete() {
    subject.debounce(200, TimeUnit.MILLISECONDS)
        .observeOn(Schedulers.io()) // add this here
        .distinctUntilChanged()
        .switchMap {
            getSearchResults(query = it)
        }
        .subscribe({ result ->
            handleResult(result)
        }, { t: Throwable? ->
            Logger.e(t, "Failed to search")
        })
}