私の活動の中で奇妙な問題が発生しました。 私はonActivityResult
の写真/ビデオの撮影から戻ってくるときに、ユーザーがカメラに名前を付けることができるダイアログを表示しています。 ユーザーが[OK]を押すと、ファイルをコピーする要求されたファイル名を持つサブジェクトにonNext()
を送信します(進行状況ダイアログが表示されます)。subscribeOn()が別のスレッドで呼び出されていても、メインスレッドで観測可能な実行が行われます
何らかの理由で、私がsubscribeOn(Schedulers.io())
を呼び出したにもかかわらず、コピーを行うmap()
関数が常にメインスレッドで呼び出されます。 observeOn(Schedulers.io())
からsubscribeOn(Schedulers.io())
呼び出しを変更
@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);
}
});
}
問題を解決しました。 まだ動作しなかった理由を知りたいのですが...
。 RxJavaをしばらく使用すると、 'subscribeOn'スレッドが、最初の' observeOn'までのすべてのダウンストリーム演算子または指定されたスケジューラーを持つ演算子に適用されていることが確かめられました。それは真実ではありませんか?この場合、 'subscribeOn'の後のスレッド選択のルールは何ですか? – AndroidEx
'subscribeOn'エフェクトは上流に行き、イベントのソースに近づきます。それをこれと考えてください。ソースはありますが、別のスレッドで購読したいと思っています。 'new thread(() - > source.subscribe(s))。start();'と書くといいでしょう。このようなことは 'subscribeOn'で起こります。スケジューラは、そのソースにサブスクライブするときに何が起こるかに基づいて選択されました。直ちにネットワーク接続を開くか、長いファイルの読み込みを開始すると、 'Schedulers.io()'に行きます。それが大きく計算を開始するなら、あなたは 'comput()'を行います。 – akarnokd
ありがとうございます。私がsubscribeOnの後に何が起こるかにもっと関心がありましたが、次の演算子がどのスレッドに適用されていますか。あなたの言葉からは、subscribeOnで指定されたスレッドであることが保証されていないという印象があります。 – AndroidEx