[iOS, RxSwift] Schedulers
SchedulerはDispatchQueueとほぼ同じことをやります。
RxSwiftではSchedulerによりObservableをどこで生成するか、またはObserverがシーケンスを監視する処理をどこで行うか決めることができます。
この時に使うOperatorは主にobserveOnとsubscribeOn、この2つです。
Scheduler operators
observeOn
ObserverがObservableをどのスレッドから監視するか設定することができます。observeOnでスレッドを特に特に指定しなかった場合は現在処理を行っているストリームで監視が行われます。
let backgroundScheduler = ConcurrentDispatchQueueScheduler(queue: DispatchQueue.global())
sequence1
.observeOn(backgroundScheduler)
.map { n in
print("This was performed on the background scheduler")
}
.observeOn(MainScheduler.instance)
.map { n in
print("This was performed on the main scheduler")
}
このシーケンスはObserverがbackgroundから監視するように設定し、またmainから監視するように設定したコードです。
subscribeOn
シーケンスを生成したり、disposeを呼び出す処理を行うスレッドを指定したい場合にsubscribeOnを使います。
subscribeOnでスレッドを特に指定しなかった場合はsubscribeが呼び出されたところから処理が行われます。
Observableが宣言され、実際に生成されるタイミングはsubscribeが呼び出された時点です。つまり、subscribeが呼び出されたことはシーケンスが生成されたことを意味するので、シーケンスが生成される位置をsubscribeOnを通じて指定することができます。(だからこのOperatorの名前がsubscribeOnなのか…?)
次のようなコードでシーケンスを生成するスレッドをbackgroundに設定することができます。
let sequence2 = Observable<Int>.create { observer in
observer.onNext(1)
observer.onNext(2)
return Disposables.create()
}
let backgroundScheduler = ConcurrentDispatchQueueScheduler(queue: DispatchQueue.global())
sequence2
.subscribeOn(backgroundScheduler)
.subscribe(onNext : { print($0) })
.disposed(by: disposeBag)
Serial vs Concurrent Schedulers
Serial schedulerはbackgroundから処理を行い、作業を直列で処理します。Concurrent schedulerは同じくbackgroundから行われますが、並列に処理を行うため、色んな作業を同時に処理することができます。
Concurrent schedulerを使うとRxでobserveOnとsubscribeOnを使う場合全ての作業を順調に処理することができそうですが、Serial schedulerを使う場合は直列で行う作業であることを証明しないといけないためobserveOnはDispatch queueの中でもdispatch_asyncでしか使うことができないみたいです。
Schedulerの種類
Main Scheduler
Main schedulerは直列で作業を処理させるschedulerです。メインスレッドから処理され、通常はUIの作業に使われます。SerialDispatchQueueScheduler
同じく直列で処理させるserial schedulerで、concurrent dispatch queueに割り当てが失敗した場合、serial dispatch queueで処理を行います。Serial schedulerはobserveOnに最適化されてます。また、main schedulerもこのschedulerのインスタンスです。ConcurrentDispatchQueueScheduler
並列で作業を処理させるschedulerです。backgroundから処理する時に適します。OperationQueueScheduler
並列で作業を処理させるschedulerです。NSOperationQueueで処理される作業がある場合使います。大きい作業をbackgroundから処理する時に適します。