[英]Observable runs on main thread even though subscribeOn() is called on another thread
I got a weird issue in one of my activities. 我在其中一项活动中遇到了一个奇怪的问题。 When coming back from taking a picture / video, in my
onActivityResult
I am showing a dialog that lets the user name the camera. 当从拍摄照片/视频回来时,在我的
onActivityResult
我正在显示一个对话框,让用户为相机命名。 Once the user presses OK, I send onNext()
to a subject with the requested file name that copies the file (and shows progress dialog). 一旦用户按下OK,我
onNext()
发送给具有复制文件的请求文件名的主题(并显示进度对话框)。
For some reason the map()
function that does the copy is always called on the main thread, even though I call subscribeOn(Schedulers.io())
. 由于某种原因,即使我调用
subscribeOn(Schedulers.io())
,也总是在主线程上调用执行复制的map()
函数。
@Override
protected void onActivityResult(final int requestCode, int resultCode, Intent intent) {
...
final PublishSubject<String> subject = PublishSubject.create();`
mSubscription = subject
.subscribeOn(Schedulers.io())
.map(new Func1<String, String>() {
@Override
public String call(String fileName) {
Log.I.d(TAG,"map");
return doSomeIOHeavyFuncition();
}
})
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<String>() {
@Override
public void call(final String fullPath) {
Log.d(TAG,"onNext");
doSomethingOnUI(fullPath);
subject.onCompleted();
}
}, new Action1<Throwable>() {
@Override
public void call(Throwable throwable) {
...
}
}, new Action0() {
@Override
public void call() {
...
}
});
final AlertDialog dialog = new AlertDialog.Builder
....
.create()
.show();
dialog.getButton(DialogInterface.BUTTON_POSITIVE)
.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String someString = getStringFromDialog(dialog);
dialog.dismiss();
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(input.getWindowToken(), 0);
showProgressDialog();
subject.onNext(someString);
}
});
}
Changing the subscribeOn(Schedulers.io())
call to observeOn(Schedulers.io())
solved the issue. 将
subscribeOn(Schedulers.io())
调用更改为observeOn(Schedulers.io())
解决了这个问题。 Still I would like to know why it didn't work... 我仍然想知道为什么它不起作用......
subscribeOn
and observeOn
is the mostly confused operators there are. subscribeOn
和observeOn
是observeOn
被混淆的运算符。 The former makes sure that subscription side effects happen on the specified scheduler (thread), but that doesn't mean that values will pop up on that thread as well. 前者确保订阅副作用发生在指定的调度程序(线程)上,但这并不意味着值也将弹出该线程。
For example, if your Observer opens a network connection when one subscribes to it, you don't want that to run on the main thread, therefore, you need subscribeOn to specify where that subscription and thus the network connection will be created. 例如,如果您的Observer在订阅它时打开网络连接,您不希望它在主线程上运行,因此,您需要subscribeOn来指定该订阅的位置以及因此将创建网络连接。
When data finally arrives, the emitting thread can be anything, one of the schedulers or a background plain old thread. 当数据最终到达时,发送线程可以是任何东西,调度程序之一或后台普通旧线程。 Since we don't know or don't like that thread, we want to move the observation of the data to another thread.
由于我们不知道或不喜欢该线程,我们希望将数据的观察移动到另一个线程。 This is what observeOn does: makes sure operators after it will execute their onNext logic on the specified scheduler.
这就是observeOn的作用:确保后面的运算符将在指定的调度程序上执行onNext逻辑。 Android devs use it already to move the observation of values back to the main thread.
Android开发人员已经使用它将值的观察结果移回主线程。
What's rarely explained though is what happens when you want some extra computation off the main thread before the final result lands on the main thread again: use multiple observeOn
operators: 但是很少解释的是当你想要在最终结果再次落在主线程上之前在主线程上进行一些额外的计算时会发生什么:使用多个
observeOn
运算符:
source
.observeOn(Schedulers.computation())
.map(v -> heavyCalculation(v))
.observeOn(Schedulers.io())
.doOnNext(v -> { saveToDB(v); })
.observeOn(AndroidSchedulers.mainThread())
...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.