RxSwift中的Timer
我们在项目中经常会用到定时器,先来看下swift
中使用定时器的几种方式:
Timer
//第一种写法
timer1 = Timer.init(timeInterval: 1,
target: self,
selector: #selector(timerFire),
userInfo: nil,
repeats: true)
RunLoop.current.add(timer1, forMode: .common)
//第二种写法
timer = Timer.scheduledTimer(withTimeInterval: 1,
repeats: true,
block: { (timer) in
print("定时中。。。")
})
RunLoop.current.add(timer, forMode: .common)
这两种只是写法不同而已,第一种初始化的方式创建的timer
需要手动添加到runloop
中才能启动。第二种scheduled
开头的方法,会默认把timer
加入到当前runloop
的default
模式下。但它们都需要改成common
模式,runloop
才会在滚动视图时同时也响应定时器。这个timer
的生命周期以及内存泄漏风险都需要我们自己管理。
CADisplayLink
displayLink = CADisplayLink(target: self, selector: #selector(timerFire))
displayLink?.preferredFramesPerSecond = 1
displayLink?.add(to: RunLoop.current, forMode: .common)
CADisplayLink
跟Timer
差不多,是根据屏幕刷新频率来的,也是需要添加在common
模式下。
DispatchSourceTimer
gcdTimer = DispatchSource.makeTimerSource()
gcdTimer?.schedule(deadline: DispatchTime.now(),
repeating: DispatchTimeInterval.seconds(1))
gcdTimer?.setEventHandler(handler: {
print("定时中。。。")
})
gcdTimer?.resume()
CGD中的定时器在使用时,不受主线程runloop
的影响。它会在自己所在的线程中一直执行下去,直到你suspend
或者cancel
掉它。而且还可以指定handler
所执行的线程。
RxSwift的Timer
let _ = Observable<Int>.interval(RxTimeInterval.seconds(1), scheduler: MainScheduler())
.subscribe(onNext: { (state) in
print(state)
})
.disposed(by: disposeBag)
首先,这个timer
也是不用关心runloop
方面的问题。
进去看看这个interval
函数:
public static func interval(_ period: RxTimeInterval,
scheduler: SchedulerType) -> Observable<Element> {
return Timer(
dueTime: period,
period: period,
scheduler: scheduler
)
}
参数1:RxTimeInterval
,就是DispatchTimeInterval
的别名。public typealias RxTimeInterval = DispatchTimeInterval
参数2:调度者,MainScheduler()
的视线中能看出,我们创建的是一个主线程调度者。
public init() {
self._mainQueue = DispatchQueue.main
super.init(serialQueue: self._mainQueue)
}
返回值是一个初始化的Timer
对象,timer
中保存了这些参数值,到此为止。
final private class Timer<Element: RxAbstractInteger>: Producer<Element> {
fileprivate let _scheduler: SchedulerType
fileprivate let _dueTime: RxTimeInterval
fileprivate let _period: RxTimeInterval?
init(dueTime: RxTimeInterval, period: RxTimeInterval?, scheduler: SchedulerType) {
self._scheduler = scheduler
self._dueTime = dueTime
self._period = period
}
}
这个timer
是Producer
的子类,也是一个序列。timer
中的泛型要求遵守RxAbstractInteger
协议的。这个协议也是个别名,public typealias RxAbstractInteger = FixedWidthInteger
,FixedWidthInteger
协议要求遵守它的实例都是用固定大小的整数类型。所以我们在创建序列的时候把泛型指定为Int
。
在创建了timer
后,我们又进行了订阅,熟悉RxSwift核心逻辑的话,就会清楚订阅信号后,内部会创建一个匿名的观察者,然后返回创建的销毁者中会调用timer序列
的订阅函数,这里又根据你指定的线程在不同的分支中走了timer序列
的run
:
func run<Observer: ObserverType>(_ observer: Observer,
cancel: Cancelable) -> (sink: Disposable,
subscription: Disposable) {
if self._period != nil {
let sink = TimerSink(parent: self, observer: observer, cancel: cancel)
let subscription = sink.run()
return (sink: sink, subscription: subscription)
} else {
......
}
}
这里还是RxSwift核心逻辑熟悉的路子,创建TimerSink
并调用run
:
final private class TimerSink<Observer: ObserverType> : Sink<Observer> where Observer.Element : RxAbstractInteger {
typealias Parent = Timer<Observer.Element>
private let _parent: Parent
private let _lock = RecursiveLock()
init(parent: Parent, observer: Observer, cancel: Cancelable) {
self._parent = parent
super.init(observer: observer, cancel: cancel)
}
func run() -> Disposable {
return self._parent._scheduler.schedulePeriodic(0 as Observer.Element,
startAfter: self._parent._dueTime,
period: self._parent._period!)
{ state in
self._lock.lock(); defer { self._lock.unlock() }
self.forwardOn(.next(state))
return state &+ 1
}
}
}
run
里面主要就是schedulePeriodi
,起始时间默认为0,后面两个都是timer序列
的间隔时间,最后还有个闭包。这个函数会在我们外面设置的那个主线程scheduler
中调用,为了防止多线程调用导致数据错误,这里加了线程锁。state &+ 1
也对应了FixedWidthInteger
协议,防止溢出。继续钻进去:
MainScheduler
的父类SerialDispatchQueueScheduler
中schedulePeriodi
的实现:
public func schedulePeriodic<StateType>(_ state: StateType,
startAfter: RxTimeInterval,
period: RxTimeInterval,
action: @escaping (StateType) -> StateType) -> Disposable {
return self.configuration.schedulePeriodic(state,
startAfter: startAfter,
period: period,
action: action)
}
又是一个接口:
func schedulePeriodic<StateType>(_ state: StateType,
startAfter: RxTimeInterval,
period: RxTimeInterval,
action: @escaping (StateType) -> StateType) -> Disposable {
let initial = DispatchTime.now() + startAfter
var timerState = state
let timer = DispatchSource.makeTimerSource(queue: self.queue)
timer.schedule(deadline: initial, repeating: period, leeway: self.leeway)
var timerReference: DispatchSourceTimer? = timer
let cancelTimer = Disposables.create {
timerReference?.cancel()
timerReference = nil
}
timer.setEventHandler(handler: {
if cancelTimer.isDisposed {
return
}
timerState = action(timerState)
})
timer.resume()
return cancelTimer
}
看到这里一下就明白了,从刚开始的参数类型开始就一直和GCD有关联,原来就是用序列封装了DispatchSourceTimer
,在定时器触发时发送序列的.next
信号。在序列销毁时cancel
掉timer
。
总结
- 创建
Timer
序列时,保存需要的参数。 - 订阅信号时构建
TimerSink
管道。 - 管道
run
起来,用 GCD 中的 Timer 在eventHandler
中发出信号。
今天的文章RxSwift中的Timer分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/14206.html