RxSwift - ObserveOn VS SubscribeOn

Observable subscription


首先了解一下Observable subscription的工作情況,我們可以把訂閱分爲以下3個部分:


1)首先我們定義一個Observable,在某些情況下我們會在閉包內提供一些代碼,該部分代碼會執行相應的工作並且發送值(elements)給任意的觀察者(observer)。當我們使用create操作符創建了該Observable,閉包內的代碼就被存儲起來用於後續的執行,而不是馬上執行。如果當前沒有觀察者(observer),那麼Observable僅僅是等待被訂閱,不會執行任何操作。

2)當我們使用不同的操作符(operators)來處理被髮送的值(elements),比如像:map,filter等等,這時候閉包仍然沒有執行任何操作,我們這裏僅僅是對Observable進行了部分的轉換和過濾,相當於創建了一個更特別的Observable,而不是最初的Observable。

3)一直到我們調用subscribe(...)方法,這時候Observable開始工作起來。調用subscribe(...)方法將執行我們之前在閉包中所編寫的代碼。


對於上面的內容,有倆點需要明白:

1)訂閱部分的代碼(subscription code),該部分內容是位於上圖的Observable.create{...}中的代碼,在我們調用subscribe()之後會執行代碼併產生值(elements)

2)觀察部分的代碼(observation code),是我們觀察到被髮送值(elements)的地方,這部分代碼,我們經常使用,如:onNext: {...}, onCompleted: {...}等,這些地方就是我們進行觀察中的地方。



Schedulers

RxSwift爲我們提供了大量的預先定義的觀察者,並且能夠滿足我們大多數時候的使用。官方的內容請看這裏。 在這裏我們只需要使用兩個:

1)MainScheduler.instance,它保證scheduler工作在主線程(main thread)

2)ConcurrentDispatchQueueScheduler是使用GCD執行給定列隊的工作


Subscribing and subscribeOn

現在瞭解一下subscribeOn操作符,它允許我們改變訂閱部分代碼(subscription code)將被執行的線程scheduler.



默認情況下訂閱部分的代碼(subscription code)將被跟你調用subscribe()方法在同一個線程,除非我們使用subscribeOn進行切換線程。例如:

Observable<Int>.create { observer in
            observer.onNext(1)
            sleep(1)
            observer.onNext(2)
            return Disposables.create()
            }
            .subscribe(onNext: { el in
                print(Thread.isMainThread)
            }).disposed(by: disposeBag)
如果我們把這部分代碼放到viewDidLoad中,我們將看到會阻塞主線程,因爲訂閱部分代碼中使用了sleep函數。我們的onNext代碼中將打印出兩個true,因爲我們一直處於主線程。即主線程進行訂閱,主線程創建observable,主線程執行onNext。

[main] subscribe() -> [main] creat {...} -> [main] onNext {...}
現在我們改變訂閱(subscription)的scheduler,插入subscribeOn操作符

  Observable<Int>.create { observer in
            observer.onNext(1)
            sleep(1)
            observer.onNext(2)
            return Disposables.create()
            }
            .subscribeOn(ConcurrentDispatchQueueScheduler(qos: .background))
            .subscribe(onNext: { el in
                print(Thread.isMainThread)
            }).disposed(by: disposeBag)
這裏將打印倆次false,因爲我們將主線程轉換到了後臺線程。

[main] subscribe() -> [background] creat {...} -> [background] onNext {...}


Observing and observeOn

現在我們來看看觀察序列中值(elements)的部分,如下圖所示:


在上面的例子中,我們轉換了訂閱到後臺線程列隊,但是很多時候,我們想在onNext {...}中更新UI,所以需要回到主線程,那麼這裏我們就可以使用observerOn,如下:

Observable<Int>.create { observer in
            print(Thread.isMainThread)
            observer.onNext(1)
            sleep(1)
            observer.onNext(2)
            return Disposables.create()
            }
            .observeOn(MainScheduler.instance)
            .subscribeOn(ConcurrentDispatchQueueScheduler(qos: .background))
            .subscribe(onNext: { el in
                print(Thread.isMainThread)
            }).disposed(by: disposeBag)
代碼執行結果爲,false -> true -> true,observeOn和subscribeOn的先後順序沒什麼關係。代碼執行順序如下:

[main] subscribe() -> [background] creat {...} -> [main] onNext {...}

以上內容參考這裏,官方相關介紹這裏。


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