我目前有一个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,看来我做得正确。
答案 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")
})
}