ストリーム操作にRxAndroidを使用しています。私の実際の使用例では、サーバーからリストを取得しています(Retrofitを使用)。私はスケジューラを使用してバックグラウンドスレッドで作業を行い、Android UI(メイン)スレッドで最終的な放出を取得しています。
これはネットワークコールではうまく機能しますが、ネットワークコール後のオペレータはバックグラウンドスレッドを使用せず、メインスレッドで呼び出されることに気付きました。
myService.fetchSomeIntegersFromServer()
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.filter(integer -> {
System.out.println(Looper.getMainLooper().getThread() == Thread.currentThread());
return true;
})
.subscribe(integer1 -> {});
すべての操作がバックグラウンドスレッドで実行されることを確認するにはどうすればよいですか?
TL; DR:observeOn(AndroidSchedulers.mainThread())
をfilter(...)
の下に移動します。
subscribeOn(...)
は、Observable
が動作するbeginスレッドを指定するために使用されます。 subscribeOn
への後続の呼び出しは無視されます。
したがって、次のように記述すると、everythingがSchedulers.newThread()
で実行されます。
myService.fetchSomeIntegersFromServer()
.subscribeOn(Schedulers.newThread())
.filter(integer -> {
System.out.println(Looper.getMainLooper().getThread() == Thread.currentThread());
return true;
})
.subscribe(integer1 -> { doSomething(integer1); });
今、もちろん、これはあなたが望むものではありません:メインスレッドでdoSomething
したいです。
ここで、observeOn
が配置されます。すべてのアクションafterobserveOn
は、そのスケジューラで実行されます。したがって、この例では、filter
がメインスレッドで実行されます。
代わりに、observeOn
をsubscribe
の直前に移動します。
myService.fetchSomeIntegersFromServer()
.subscribeOn(Schedulers.newThread())
.filter(integer -> {
System.out.println(Looper.getMainLooper().getThread() == Thread.currentThread());
return true;
})
.observeOn(AndroidSchedulers.mainThread())
.subscribe(integer1 -> { doSomething(integer1) });
これで、filter
が「新しいスレッド」で発生し、doSomething
がメインスレッドで発生します。
さらに進むには、observeOn
を複数回使用できます。
myService.fetchSomeIntegersFromServer()
.subscribeOn(Schedulers.newThread())
.observeOn(Schedulers.computation())
.filter(integer -> {
System.out.println(Looper.getMainLooper().getThread() == Thread.currentThread());
return true;
})
.observeOn(AndroidSchedulers.mainThread())
.subscribe(integer1 -> { doSomething(integer1) });
この場合、フェッチは新しいスレッドで発生し、フィルタリングは計算スレッドで発生し、doSomething
はメインスレッドで発生します。
チェックアウト ReactiveX-SubscribeOn operator 公式ドキュメント。