我在其中一个Activity中遇到了奇怪的问题。当从拍照/视频返回时,在我的onActivityResult
函数中,我显示一个对话框让用户命名相机名称。一旦用户按下确定,我使用请求的文件名向主题发送onNext()
,并复制该文件(并显示进度对话框)。
出于某种原因,即使我调用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);
}
});
}
将subscribeOn(Schedulers.io())
调用更改为observeOn(Schedulers.io())
解决了问题。但我仍然想知道为什么它之前没起作用...
subscribeOn
线程适用于所有的下游操作符,直到第一个observeOn
或指定了调度器的操作符出现。这不是真的吗?那么在subscribeOn
之后如何选择线程? - AndroidExsubscribeOn
效果向上游靠近事件源。可以这样想,你有一个事件源,但是你想在不同的线程上订阅它。你可以编写new Thread(() -> source.subscribe(s)).start();
。subscribeOn
中会发生类似的事情。你根据订阅该源时发生的情况选择调度程序。如果它立即打开网络连接或开始读取长文件,则使用Schedulers.io()
。如果它开始进行大量计算,则使用computation()
。 - akarnokd