嗨,今天講observable。
Rx的一個核心觀念就是observable(或叫sequence ),口訣就是,Everything is a SEQUENCE,大意就是在Rx的世界,都是由observable構成。
在Rx各種教學文件上,都能看到下方的這種示意圖,所以看懂這張圖是今天要講的第一件事!順便也會帶一下常見的英文名詞,往後看到比較不會理解錯誤。
圖一、Completed示意圖
圖二、Error示意圖
.next
event,observable會向訂閱者發送(emit)元素,元素可以是Int、Void或是自定義的Class。.completed
event,表示對訂閱者說『元素都已經發送完畢了,不在發送任何的事件』。.error
event,表示對訂閱者說『發生錯誤了』,此時,也會停止發送任何的事件。回過頭來解釋上面第一張圖,我們可以解釋成『向訂閱者發送一個數字1,然後間隔了一下,再發送數字3跟7,然後結束了這個Observable』,第二張圖則是,『 向訂閱者發送數字1、3、7後發生錯誤』。
可以發現到,當發送.completed
跟.error
後,Observable就會結束(Terminated),此時任務已完成,資源就會被回收了。所以,光有Observable是沒有任何作用,需要被訂閱(Subscribe),才會開始發送元素!下面我們談談怎麼建立Observable和如何被訂閱。
建立一個Observable有許多方式,這裡先用最簡單的方式,使用of
建立一個有限序列,of
可將多個相同型態的元素,建立成一個Observable
let observable = Observable.of(1, 3, 7)
使用.subscribe
來訂閱Observable,藉此來接收值得變化
let disposeBag = DisposeBag()
observable
.subscribe(onNext: { element in
print(element)
}, onError: { error in
print(error)
}, onCompleted: {
print("onCompleted")
}, onDisposed: {
print("onDisposed")
})
.disposed(by: disposeBag)
從程式碼可以對應到我們上面的描述,當訂閱者收到Observable發出的.next、.error、.completed事件時,會依據我們定義好的程式執行。執行結果如下,
1
3
7
onCompleted
onDisposed
上個範例有提到Dispose,這是跟Observable銷毀機制有關,上個範例使用的是有限序列,所以元素發送完畢,自然接著發送.completed
,但大多是專案開發時,都不是有限序列這麼簡單。
實際狀況可能是『在ViewModel有一個名為Observable<[Order]>來存訂單資料,是藉由呼叫API來取得的,另外在View以TableView呈現,所以,Observable<[Order]>要與TableView DataSource Binding一起,這樣若是重新呼叫API,資料更新,畫面也會更新』,以上的情境下,Observable某種程度算是無限的,所以就不得不考慮何時需要把Observable銷毀,下面我們來談談,Observable的銷毀機制。
想像我們有一個袋子,裡面放著球,當你把這個袋子丟掉,球也一起被丟掉了,從上個例子來看,disposeBag
就是那個袋子,訂閱者就是那顆球,我們將訂閱者裝進去,當ViewController deinit時,disposeBag
會跟著被銷毀,隨之訂閱者的資源也會一同銷毀,概念就是這麼簡單~
2020.11.02補充,當初在寫本篇,把Dispose跟Observer做了等號,這是不正確的,確切來說裝入袋子的是Disposable,當我們
subscribe()
時,就會產生一個Disposable,當今天deinit
時,Observable卻還沒結束,這時裝在DisposeBag中的所有Disposable就會執行dispose()
,藉此來釋放資源,感謝t19960804大大提點
如果你撰寫程式時,進行了.subscribe()
卻忘記寫.disposed()
,這很有可能會造成Memory leak,這時Swift compiler也會提醒你,在Xcode上會看到黃色的提醒,這時記得加上.disposed()
,很貼心吧!
補充:
若想要做實驗,可以使用interval
來建立一個『固定間隔時間,發送元素』的Observable
let observable = Observable<Int>.interval(.milliseconds(500), scheduler: MainScheduler.instance)
接著步驟如下:
present
到 B ViewController.next
, .completed
, .disposed
的變化onDisposed
今天介紹了observable的生命週期,如何建立到銷毀,明天還是繼續談Observable的其他的建立方式,就這樣,掰掰
版主你好
我想請問一下
“Observable的銷毀機制” > disposeBag就是那個袋子,訂閱者就是那顆球,我們將訂閱者裝進去,當ViewController deinit時,disposeBag會跟著被銷毀
為什麼被銷毀的卻是訂閱者?
感謝大大留言,對此,我重新再看了一下Disposable
這邊講得不太對,不應該說是把訂閱者裝進袋子,確切來說裝入袋子的是Disposable,當我們subscribe()
時,就會產生一個Disposable,當今天deinit
時,Observable卻還沒結束,這時裝在DisposeBag中的所有Disposable就會執行dispose()
,來釋放資源
舉個例子說,NotificationCenter+Rx.swift
中,Observable.create {}
會建立並回傳一個Disposable,closure當中就會撰寫需要當結束的時候要做什麼事情,當Observable順利結束會執行這closure,或是突然提前結束,DisposeBag也會執行這closure。
若仍有誤再麻煩補充or討論(鞠躬
P.S.當初寫的時候,把Dispose跟Observer做了等號,現在回頭看是不正確的,在原文加以補充
感謝版主回覆
所以Disposable = 被subscribe的Observerable
這樣理解是不是就符合“Observable的銷毀機制”這個標題?
直接等號似乎怪怪的,比較像是訂閱後的產物
Disposable = Observerable被subscribe後所產生的產物,用來當Observable提前結束時可用來釋放資源
這樣就符合銷毀機制這標題