在之前我们看
RxSwift
源码时,经常看到一个Scheduler
,但是没有去管他, 其实Scheduler
是RxSwift
针对多线程的一套封装, 大部分是使用GCD
,另外还有部分是Operation
. 目的是为了让用户更直接了当的决定在哪一个队列中去异步执行观察/订阅.
先来看一个例子:
DispatchQueue.global().async {
print("请求数据\(Thread.current)")
self.actionBtn.rx.tap
.subscribe(onNext: { () in
print("tap =--- \(Thread.current)")
})
}
问: 在按钮点击后打印结果是在哪个线程?
打印结果如下:
请求数据<NSThread: 0x60000241d440>{number = 3, name = (null)}
tap =--- <NSThread: 0x60000244d980>{number = 1, name = main}
问题:
为什么我们在子线程对 tap
序列订阅, 执行响应时会自动回到主线程呢?
ControlEvent 默认调度解析:
cmd
+ 点击 .tap
extension Reactive where Base: UIButton {
/// Reactive wrapper for `TouchUpInside` control event.
public var tap: ControlEvent<Void> {
return controlEvent(.touchUpInside)
}
}
return
了一个 controlEvent
, 继续点击 controlEvent
.
发现一个疑似调度者处理的东西, 再点进去
.ensureRunningOnMainThread()
public class func ensureRunningOnMainThread(errorMessage: String? = nil) {
#if !os(Linux) // isMainThread is not implemented in Linux Foundation
guard Thread.isMainThread else {
rxFatalError(errorMessage ?? "Running on background thread.")
}
#endif
}
发现啥也没干, 没在主线程执行就提示了一句. 好吧.
那说明在 执行序列创建闭包调用 之前,就已经回到主线程了.
通过之前核心逻辑分析经验,我们知道 序列创建闭包调用 是在订阅之后执行的
.
也就是说 .tap
返回了一个 ControlEvent
的序列, 而且ControlEvent
并非继承自 Producer
, 那么 ControlEvent
必然自己实现了 subscribe
方法, 那么这个序列在订阅时就来到了如下方法:
public func subscribe<Observer: ObserverType>(_ observer: Observer) -> Disposable where Observer.Element == Element {
return self._events.subscribe(observer)
}
其中 self. _events
是谁? 我们看下 init
方法
public init<Ev: ObservableType>(events: Ev) where Ev.Element == Element {
self._events = events.subscribeOn(ConcurrentMainScheduler.instance)
}
先不管 subscribeOn
下一篇文章我会讲解, 意思就是在指定队列订阅, 并且返回一个新序列. 那么我们 cmd + ConcurrentMainScheduler
看init方法
private init(mainScheduler: MainScheduler) {
self._mainQueue = DispatchQueue.main
self._mainScheduler = mainScheduler
}
至此, ControlEvent
类型序列在默认调度时流程解析完毕, rx
在处理该类型序列的订阅时 , 默认执行在主队列.
网友评论