RxSwift的Timer计时的时候是不会受到UI滑动事件影响的,所以我们今天来探究一下RxSwift的Timer是怎么实现的。
首先来看三个我们平时实现计时功能的方式
可以看出不管是Timer还是CADisplayLink实现的timer都是要依赖于runloop的,所以在普通情况下会受到UI滑动事件的影响,当然有其他的方式可以解决,这个问题不是我们今天的核心。所以我们着重来看GCD方式创建timer的方式,我们都知道GCD创建timer的方式是不会受到UI滑动事件的影响,先猜测一下RxSwift对于Timer的实现也是使用了GCD的方式,在系统的GCD上做封装。
在这里我们先来看一下RxSwift怎么实现timer
创建好了之后,怎么下手呢,在上一篇文章中RxSwift核心探究中有介绍Observable是什么,有疑问的话可以先去看RxSwift核心探究。
我们这里直接看timer这个方法是怎么实现的
在这里是不是一眼就相中了那个dueTime,因为这里比较清晰,直接去看dueTime的类型
看到RxTimeInterval这个别名实际指向的类型,是不是基本验证了我们的猜测。
但是我们还是需要找到它是怎么实现的,这时候再来看看返回的Timer()方法。
看到继承的父类了嘛Pruducer,是不是有点熟悉了。事不宜迟,所以我们直接去看run方法吧。TimerSink更熟悉了吧,不能说一摸一样,是真的一摸一样。
这里有点不一样了哦,链式调用,看最后一个 schedulePeriodic方法,注意这里返回的是每次加1。而且在这里就直接开始发布订阅了,也就是我们核心的三步,这里直接在订阅完成之后就发布了一个订阅。
有这个想法之后,那我们就不用费时费力再去一步一步寻找了,直接去实现SchedulerType的协议的类里去找关键代码
SerialDispatchQueueScheduler,ConcurrentDispatchQueueScheduler,ConcurrentMainScheduler,三个都是实现了SchedulerType协议的。
直接找到最终结构体DispatchQueueConfiguration的扩展中
看到这里,是不是验证了RxSwift的Timer确实是利用自己的逻辑对GCDTimer的封装。
扩展:怎么停止Timer?
看到核心这里创建的时候怎么停止。红色标注的地方,Disposble.create.isDisposed来控制,似乎有了一点思路。
1.重新创建垃圾袋。
2.将timer从disposeBag中取出来,手动的关闭订阅。
第一种思路明显是有点不合适的,重新创建disposeBag,disposeBag如果 还管理其他的序列,会清除掉其他的序列,所以是不太合适的。
其实RxSwift 已经做好了相关的一些方法,比如
使用.take来控制需要定时多少次,次数结束后会直接completed。
如果想要手动的关闭Observable怎么做呢,可以选择不使用页面的disposeBag。
需要注意的是这里subscribe这里返回的是Disposable
也可以使用CompositeDisposable 把Disposable 装起来,然后一起释放。
也可以使用CompositeDisposable.DisposeKey
这里insert方法返回的是CompositeDisposable.DisposeKey。
最后:
如果需要实现手动暂停和开始(不是关闭)Timer应该怎么做?
后续更精彩。。。。