美文网首页
RxSwift中的Scheduler

RxSwift中的Scheduler

作者: Sweet丶 | 来源:发表于2021-11-01 16:55 被阅读0次

我们使用RxSwift中的定时器时需要传一个scheduler参数(有关使用可查看RxSwift中的定时器),我们会困惑应该创建哪个scheduler合适(我称为调度器)。接下来我们来了解一下RxSwift中的调度器,下图是整理的类结构图

Schedule类结构图.png
一、ImmediateSchedulerType

ImmediateSchedulerTypeprotocol类型的,内部有两个方法:
出现RecursiveImmediateScheduler类是用来递归调用action。

/// 等待继承协议的必须实现
func schedule<StateType>(_ state: StateType, action: @escaping (StateType) -> Disposable) -> Disposable

/// 协议中实现的方法,使用RecursiveImmediateScheduler调度器来完成递归调用action
public func scheduleRecursive<State>(_ state: State, action: @escaping (_ state: State, _ recurse: (State) -> Void) -> Void) -> Disposable {
    let recursiveScheduler = RecursiveImmediateScheduler(action: action, scheduler: self)
    recursiveScheduler.schedule(state)
    return Disposables.create(with: recursiveScheduler.dispose)
}
二、OperationQueueScheduler

OperationQueueScheduler类创建实例时需要指定一个OperationQueue和任务的优先级queuePriority,在后续使用这个调度器调度任务时,我们的action都会放在一个BlockOperation的block中,并且设置BlockOperation的优先级为实例的queuePriority,然后把opt添加到queue中执行。
作用:使用这个调度器调度任务时,任务会在指定的queue中以指定的优先级执行。

// 使用递归调用的一个示例
let queue = OperationQueue()
queue.maxConcurrentOperationCount = 1// 串行队列
let scheduler = OperationQueueScheduler(operationQueue: queue)
// 递归调用的作用
_ = scheduler.scheduleRecursive(1) { state, action in
    print("调用一次---------》")
    if state < 6 {
        action(state + 1)
    } else {
        print("state大于临界值")
    }
}
三、CurrentThreadScheduler

CurrentThreadScheduler调度器,特别之处在于:如果当前任务代码里面又开启一个新的任务,这个情况CurrentThreadScheduler会将先将任务包装成ScheduledItem加到队列中,等执行完当前任务后,遍历队列中的任务,逐个调用。 RxSwift 利用线程特有数据(TSD)解决循环调用的问题

四、SchedulerType

SchedulerType是一个协议,有以下1个必须实现 + 1个可选实现 + 1个递归调度的方法.
下面代码中的SchedulePeriodicRecursive类中调用start()时是会调用下面的scheduleRecursive方法; AnyRecursiveScheduler类的实例执行它的schedule方法时, 内部又会回调self.scheduler.scheduleRelative方法。可以看到SchedulerType相比它继承的协议是多了对定时任务调度的支持。

/// 用于经过dueTime的相对时间后执行action,继承的类需要自己实现。
func scheduleRelative<StateType>(_ state: StateType, dueTime: RxTimeInterval, action: @escaping (StateType) -> Disposable) -> Disposable
/// 协议中可选实现方法,周期性调用action
public func schedulePeriodic<StateType>(_ state: StateType, startAfter: RxTimeInterval, period: RxTimeInterval, action: @escaping (StateType) -> StateType) -> Disposable {
    let schedule = SchedulePeriodicRecursive(scheduler: self, startAfter: startAfter, period: period, action: action, state: state)
    return schedule.start()
}
/// 协议中实现的方法,使用AnyRecursiveScheduler来完成对action的dueTime后递归调用
func scheduleRecursive<State>(_ state: State, dueTime: RxTimeInterval, action: @escaping (State, AnyRecursiveScheduler<State>) -> Void) -> Disposable {
    let scheduler = AnyRecursiveScheduler(scheduler: self, action: action)
    scheduler.schedule(state, dueTime: dueTime)
    return Disposables.create(with: scheduler.dispose)
}
五、ConcurrentDispatchQueueScheduler

遵守SchedulerType协议 ,用于在并发队列中调度任务的,初始化这个实例时会创建并发队列,而后在调用协议中的几个schedule...方法时,会在并发队列中执行它的任务。

public final func schedule<StateType>(_ state: StateType, action: @escaping (StateType) -> Disposable) -> Disposable {
    self.configuration.schedule(state, action: action)
}

public final func scheduleRelative<StateType>(_ state: StateType, dueTime: RxTimeInterval, action: @escaping (StateType) -> Disposable) -> Disposable {
    self.configuration.scheduleRelative(state, dueTime: dueTime, action: action)
}

public func schedulePeriodic<StateType>(_ state: StateType, startAfter: RxTimeInterval, period: RxTimeInterval, action: @escaping (StateType) -> StateType) -> Disposable {
    self.configuration.schedulePeriodic(state, startAfter: startAfter, period: period, action: action)
}
六、ConcurrentMainScheduler

这个类设计为了单例模式,与ConcurrentDispatchQueueScheduler的区别在于任务会在主线程执行,可以看到如下的schedule方法:判断当前如果是主线程则直接执行action, 如果不是则回到主线程中调用action。

    /// Singleton instance of `ConcurrentMainScheduler`
    public static let instance = ConcurrentMainScheduler(mainScheduler: MainScheduler.instance)

    public func schedule<StateType>(_ state: StateType, action: @escaping (StateType) -> Disposable) -> Disposable {
        if DispatchQueue.isMain {  return action(state)  }
        let cancel = SingleAssignmentDisposable()
        self.mainQueue.async {
            if cancel.isDisposed {
                return
            }
            cancel.setDisposable(action(state))
        }
        return cancel
    }
七、SerialDispatchQueueScheduler

这个类通过名字我们可以知道是串行调度器,类似于串行队列。于ConcurrentDispatchQueueScheduler的区别在于便利构造方法中,内部创建的是串行队列,执行action也是在这个串行队列中。

八、MainScheduler

这个调度器是继承自SerialDispatchQueueScheduler的,用于在主线程中调度任务,我们主要使用它下面两个单例:

  • MainScheduler.instanceMainScheduler类型的,
  • MainScheduler.asyncInstanceSerialDispatchQueueScheduler类型的;

这两个类型在执行schedule方法时,都是转为调用scheduleInternal方法,而两个类的scheduleInternal中区别是:

  • MainScheduler是判断当前是主线程会直接执行,不是主线程则异步回调到主线程执行action;
  • SerialDispatchQueueScheduler中是不管当前是否主线程,直接异步回调到主线程再执行。
    /// Singleton instance of `MainScheduler`
    public static let instance = MainScheduler()

    /// Singleton instance of `MainScheduler` that always schedules work asynchronously
    /// and doesn't perform optimizations for calls scheduled from main queue.
    public static let asyncInstance = SerialDispatchQueueScheduler(serialQueue: DispatchQueue.main)

    override func scheduleInternal<StateType>(_ state: StateType, action: @escaping (StateType) -> Disposable) -> Disposable {
        let previousNumberEnqueued = increment(self.numberEnqueued)
        if DispatchQueue.isMain && previousNumberEnqueued == 0 {
            let disposable = action(state)
            decrement(self.numberEnqueued)
            return disposable
        }
        let cancel = SingleAssignmentDisposable()
        self.mainQueue.async {
            if !cancel.isDisposed {
                cancel.setDisposable(action(state))
            }
            decrement(self.numberEnqueued)
        }
        return cancel
    }
九、VirtualTimeScheduler

虚拟时间调度器基类,在使用时首先需要自己手写一个实现VirtualTimeConverterType协议的类作为虚拟与真实的转化器;
调度任务的过程:先将时间转化为虚拟时间 --》 把任务组装成带时间戳的VirtualSchedulerItem任务项 --》放到内部的PriorityQueue队列中 --》调用start()方法后,在主线程中遍历PriorityQueue调用每个action,并且每执行action前将self.currentClock设置为action.time
这个调度器的特别的作用是PriorityQueue队列中保存了调用记录和当前的调用进度。

// 需要子类实现自己的虚拟时间与真实时间转化的协议VirtualTimeConverterType
open class VirtualTimeScheduler<Converter: VirtualTimeConverterType>
    : SchedulerType
十、HistoricalScheduler

继承自VirtualTimeScheduler, 是一个有着自己的虚拟与真实时间转化器HistoricalSchedulerTimeConverter的一个特例。

相关文章

网友评论

      本文标题:RxSwift中的Scheduler

      本文链接:https://www.haomeiwen.com/subject/piqialtx.html