RxSwift - Schedulers

Scheduler

簡單來說Scheduler就是進程執行的上下文(也可以說程序執行的上下文)。上下文(context)可以是一個線程(thread),一個派發列隊(dispatch queue),或者是用於OperationQueueScheduler中的NSOperation。這裏有一個好例子說明調度者怎樣被使用:

由上圖可知,我們可能在後臺調度者中(Background Scheduler)進行網絡請求,然後緩存數據。並傳遞數據給所有的訂閱者,大多數時候會回到MainScheduler,MainScheduler位於主線程的頂部。因爲更新UI操作,必須在主線程。所以會切換到MainScheduler。注意:調度者(Scheduler)不是線程。

幾種內嵌Scheduler(Builtin schedulers

CurrentThreadScheduler (Serial scheduler)

當前線程的調度者,這也是默認的調度者用於產生元素。

MainScheduler (Serial scheduler)

MainScheduler是主線程的一部分,這個調度者是經常用於處理用戶界面的改變(即執行UI工作)和執行一些高優先級的任務。長時間任務不應該在該調度者中執行,比如:向服務器請求數據,其他繁重的任務。除此之外,如果你執行鏈式響應(side effects)來更新UI,你必須轉換到MainScheduler,保證屏幕UI更新成功。MainScheduler也用於執行所有的計算,當使用Units、Driver。Driver確保了計算經常被執行在MainScheduler,讓你有能力直接綁定數據到用戶界面。下面是MainScheduler類的部分源碼:
public final class MainScheduler : SerialDispatchQueueScheduler {

    private let _mainQueue: DispatchQueue

    /// Initializes new instance of `MainScheduler`.
    public init() {
        _mainQueue = DispatchQueue.main
        super.init(serialQueue: _mainQueue)
    }

    /// Singleton instance of `MainScheduler`
    public static let instance = MainScheduler()
}
由上面代碼可知,MainScheduler是繼承於SerialDispatchQueueScheduler,有instance單例,並且初始化時指定了運行線程爲主線程(DispatchQueue.main),我們經常使用MainScheduler.instance來獲取主線程並且配合observeOn操作符進行使用。

SerialDispatchQueueScheduler (Serial scheduler)

SerialDispatchQueueScheduler管理着串行派發列隊(serial DispatchQueue)的抽象工作。它將確保即使是併發派發列隊(concurrent dispatch queue )被傳遞,也將被轉換爲串行。在使用observeOn操作符的時候,這個調度者有幾個非常大的優勢。你能夠使用該調度者處理後臺任務,而且使用串行的方式更好的執行。例如:如果你有一個應用跟服務端進行交流(as in a Firebase or GraphQL application),你可能想避免派發多個,同時的請求,這會給服務端導致太大的壓力。該調度者是完成滿足你的工作就像一個串行任務列隊一樣,按順序執行。

ConcurrentDispatchQueueScheduler (Concurrent scheduler)

ConcurrentDispatchQueueScheduler跟SerialDispatchQueueScheduler有些類似,也是管理DispatchQueue的抽象工作.主要的區別是這次不是串行列隊而是一個併發列隊。當使用observeOn的時候,該調度者並不算最佳選擇。ConcurrentDispatchQueueScheduler是多任務、長耗時、需要同步執行任務的首選。

OperationQueueScheduler (Concurrent scheduler)

OperationQueueScheduler非常相似於ConcurrentDispatchQueueScheduler,但是並不是跟DispatchQueue一起工作,而是與NSOperationQueue一起工作。有時,你需要更多的對於併發的工作控制權限,但是你不能夠在ConcurrentDispatchQueueScheduler進行操作,可以選擇使用OperationQueueScheduler。
如果需要很好的設置最大數量的併發工作,OperationQueueScheduler是很好的選擇。因爲你能夠使用maxConcurrentOperationCount來設置最大的操作數量

TestScheduler

非常特殊,它是用於測試的,所以注意了,不能夠在正常的開發中使用,應該僅僅是用於測試,它是RxTest庫的一部分。

注意:有趣的事情是如果傳遞併發列隊(concurrent queue)到串行調度者(serial scheduler),RxSwift將確保併發列隊變成串行列隊(serial queue)。同理:如果傳遞串行列隊到併發調度者,也會將串行列隊變成併發列隊(concurrent queue)


轉換調度者(Switching schedulers)
在rx中一個最重要的事情之一就是可以有能力在任意時候轉換調度者(Switching schedulers)。沒有任何的限制,除了一個被強加的,由內部進程生成事件。
在線程這部分主要有兩個操作符:observeOn 和 subscribeOn ,常用的還是 observeOn 。observeOn是ObservableType擴展中的一個方法:
extension ObservableType {
    /**
        Wraps the source sequence in order to run its observer callbacks on the specified scheduler.
        
        This only invokes observer callbacks on a `scheduler`. In case the subscription and/or unsubscription
        actions have side-effects that require to be run on a scheduler, use `subscribeOn`.
  
        - seealso: [observeOn operator on reactivex.io](http://reactivex.io/documentation/operators/observeon.html)
        - parameter scheduler: Scheduler to notify observers on.
        - returns: The source sequence whose observations happen on the specified scheduler.
        */
    public func observeOn(_ scheduler: ImmediateSchedulerType) -> RxSwift.Observable<Self.E>
}

調用 observeOn 指定接下來的操作在哪個線程,也可以理解爲在哪個scheduler監聽Observable.一個比較典型的例子:在後臺發起網絡請求,然後解析數據,最後在主線程刷新頁面。我們可以先使用subscribeOn切換到後臺發送請求並解析數據,在使用observeOn切換回到主線程更新頁面。或者使用兩次observeOn

  sequence1
            .observeOn(backgroundScheduler)
            .map { n in
                print("This is performed on the background scheduler")
            }
            .observeOn(MainScheduler.instance)
            .map { n in
                print("This is performed on the main scheduler")
        }
調用 subscribeOn 決定訂閱者的操作執行在哪個線程。對於subscribeOn:
extension ObservableType {
    /**
        Wraps the source sequence in order to run its subscription and unsubscription logic on the specified 
        scheduler. 
        
        This operation is not commonly used.
        This only performs the side-effects of subscription and unsubscription on the specified scheduler. 
        In order to invoke observer callbacks on a `scheduler`, use `observeOn`.
    
        - seealso: [subscribeOn operator on reactivex.io](http://reactivex.io/documentation/operators/subscribeon.html)
        - parameter scheduler: Scheduler to perform subscription and unsubscription actions on.
        - returns: The source sequence whose subscriptions and unsubscriptions happen on the specified scheduler.
        */
    public func subscribeOn(_ scheduler: ImmediateSchedulerType) -> RxSwift.Observable<Self.E>
}

當然,如果我們沒有明確調用這兩個操作,後面的操作都是在當前線程執行的。對於調度者使用的簡單事例可以看這裏


參考:


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章