试图从此资源中找出一些东西:https : //www.raywenderlich.com/384-reactive-programming-with-rxandroid-in-kotlin-an-introduction
我遇到一个问题:为什么我应该在主线程而不是Schedulers.io()中调用subscribeOn()?
当我这样订阅时,我的应用程序冻结了几秒钟,并且丢了帧。
searchTextObservable
.subscribeOn(Schedulers.io())
.map { cheeseSearchEngine.search(it) }
.observeOn(AndroidSchedulers.mainThread())
.subscribe {
showResult(it)
}
然后我订阅了主线程,并在Schedulers.io()中观察了它(我也不明白为什么要那样做)应用程序完全没有冻结。
searchTextObservable
.subscribeOn(AndroidSchedulers.mainThread())
.observeOn(Schedulers.io())
.map { cheeseSearchEngine.search(it) }
.observeOn(AndroidSchedulers.mainThread())
.subscribe {
showResult(it)
}
谁能解释一下为什么这样工作吗?
编辑
// 1
private fun createTextChangeObservable(): Observable<String> {
// 2
val textChangeObservable = Observable.create<String> { emitter ->
// 3
val textWatcher = object : TextWatcher {
override fun afterTextChanged(s: Editable?) = Unit
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) = Unit
// 4
override fun onTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
s?.toString()?.let { emitter.onNext(it) }
}
}
// 5
queryEditText.addTextChangedListener(textWatcher)
// 6
emitter.setCancellable {
queryEditText.removeTextChangedListener(textWatcher)
}
}
// 7
return textChangeObservable
}
subscribeOn vs.observeOn
subscriptionOn将在给定的Scheduler上调用Observable的create方法。多少次使用subscribeOn都没有关系。Source-observable的第一个subscriptionOn(链中的第一个)始终获胜。
watchOn将在操作员之间切换线程。当上游在线程X上发出一个值时,它将在observeOn-Operator中从给定的调度程序切换到线程Y。现在,observeOn下面的所有内容都将在线程Y中进行处理。
提供的示例1的最佳猜测:使用subscriptionOn将在Schedulers#io上调用Observable#create。将在Scheduler#io的此线程上调用create-lambda中的所有内容。侦听器回调(onTextChanged)实际上可以在另一个线程上发生。在这种情况下,它是UI-Thread,因为它是某种UI元素。现在,将从UI线程(emitter.onNext(it))调用onNext。该值将在UI-Thread(.map {cheeseSearchEngine.search(it))上发送给#map运算符,而cheeseSearchEngine#search将阻止UI-Thread。
示例2:用作第一个运算符“ .subscribeOn(AndroidSchedulers.mainThread())”。实际上这没有任何效果,因为您已经在UI-Thread中。在这种情况下,将从AndroidSchedulers#mainThread调用create-lambda。就在Example1中,onNext也会在UI-Thread上发出,因为UI会触发onTextChanged-Event。然后将值通过observeOn(Schedulers.io())放入。来自observeOn-point的所有内容都将在Schedulers#io-Thread上执行。当map执行某些HTTP请求(或某种长时间运行的IO)时,这将不会阻止ui。映射完成并向下游发出下一个值后,下一个observeOn(AndroidSchedulers.mainThread())将切换回UI-Thread。因此,由于您位于UI线程上,因此现在可以安全地更改subscription-lambda中的UI。
摘要:使用subscriptionOn只会在给定的Scheduler-Thread上调用create lambda。create中已注册侦听器的回调可能在另一个线程上发生。这就是为什么Example1将阻止UI-Thread而Example2将不会阻止UI-Thread的原因。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句