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 {...}
現在我們來看看觀察序列中值(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 {...}