- Observable :
- Là một sequence , nó bắn các event qua các khoảng thời gian khác nhau. Event có thể chứa value Int ,String , Custom type hay là một gesture, 1 tap khi nhấn button.
- Life cycle của nó như sau : khi emit 1 event đó là next, Khi complete or error là kết thúc 1 stream.
-Observable vs observer
// OBSERVABLE //
let observable = Observable<String>.create { (observer) -> Disposable in
DispatchQueue.global(qos: .default).async {
Thread.sleep(forTimeInterval: 10)
observer.onNext("Hello dummy 🐣")
observer.onCompleted()
}
return Disposables.create()
}
// OBSERVER //
observable.subscribe(onNext: { (element) in
print(element)
}).addDisposableTo(disposeBag)
Ví dụ trên bạn có thể thấy observable là cái sẽ emit ra event, còn observer là cái nhận event.
-Tạo một observable
// ========1.Tạo từ những giá trị cho trước======= // Observable.of(1, 2, 3, 4, 5, 6)let observable = Observable<String>.create { (observer) -> Disposable in observer.onNext("merge : 🎁") return Disposables.create() }// =========2.Khi get API dùng URLSession ===========//func getRepositories(githubId:String) -> Observable<[Repository]> { guard let url = NSURL(string: "https://api.github.com/users/\(githubId)/repos") else { return Observable.just([]) } return URLSession.sharedSession .rx_JSON(NSURLRequest(URL: url)) .retry(3) .map { var data = [Repository]()if let items = $0 as? [[String: AnyObject]] { items.forEach { guard let name = $0["name"] as? String, let url = $0["url"] as? String else { return }data.append(Repository(name: name, url: url)) } }return data } }//==============3.Từ Subject vs Variable========== // struct Student { var score: Variable<Int> } let student = PublishSubject<Student>() student.asObservable() .flatMap { $0.score.asObservable() } .subscribe(onNext: { print($0) }) .addDisposableTo(disposeBag)
-Subscribing : dùng hàm subscribe để đăng kí nhận event
//Subscribe tất cả event observable.subscribe { event in print(event) }//Subscribe on next observable.subscribe(onNext: { element in print(element) })//Subscribe on next vs complete observable.subscribe(onNext: { element in print(element) },onCompleted: { print("Completed") })//Subscribe với next,complete,error .subscribe( onNext: { print($0) }, onError: { print($0) }, onCompleted: { print("Completed") } )
-Dispose : dùng để clean up, giải phóng 1 observable
Dispose Bag : trả về 1 loại giống ARC , tự giải phóng khi Owner đang subscribe vào hàm deinit giải phóng bộ nhớ.
Dispose Bag : trả về 1 loại giống ARC , tự giải phóng khi Owner đang subscribe vào hàm deinit giải phóng bộ nhớ.
// Chúng ta sẽ dispose bằng hàm, khi nào chúng ta cần dừng subscription.dispose()// Dùng 1 instance DisposeBag, sẽ tự động gọi dispose khi class hiện tại đang cần subscribe đã deinitlet disposeBag = DisposeBag() Observable.of("A", "B", "C") .subscribe { print($0) } .disposed(by: disposeBag)
-Với các observable dùng hàm "create" để tạo sẽ return 1 dispose
return Disposables.create(with: { //Clean up connection.close() database.closeImportantSomething() cache.clear() })Observable<String>.create { observer in observer.onNext("1") return Disposables.create() } .subscribe( onNext: { print($0) }, onError: { print($0) }, onCompleted: { print("Completed") }, onDisposed: { print("Disposed") } ) //.disposed(by: disposeBag)
+ Nhưng với dispose kiểu này thì phải gọi complete or error nó mới dispose => leak memory
+ Còn dùng .disposed(by: disposeBag) => Sẽ luôn luôn được giải phóng và không gây leak memory
+ Còn dùng .disposed(by: disposeBag) => Sẽ luôn luôn được giải phóng và không gây leak memory
-Chúng ta có 2 loại observable là HOT vs COLD
+ HOT : observable chỉ bắt đầu thực hiện khi có 1 observer subscribe.
Dùng trong các loại : Variables / properties / constants, tap coordinates, mouse coordinates, UI control values, current time.
Dùng trong các loại : Variables / properties / constants, tap coordinates, mouse coordinates, UI control values, current time.
+ COLD : observable luôn luôn thực hiện bất kể ko có 1 observer subscribe nào.
Dùng trong các loại : Async operations, HTTP Connections, TCP connections, streams.
Dùng trong các loại : Async operations, HTTP Connections, TCP connections, streams.
2.SubjectsLà một loại đặc biệt có thể là 1 observable(output) và cũng là 1 observer(input) . Có 4 loại subjects :
+ PublicSubject : bắt đầu rỗng và chỉ bắn ra event khi có subscribe.
+ BehaviorSubject : bắt đầu với giá trị khởi tạo và sẽ bắn kèm cho subscribe mới với 1 event gần nhất.
+ ReplySubject : giống behavior, và có thể para : buffersize để xác định số lập lại.
+ Variable : wrap một BehaviorSubject và lưu trữ giá trị như một trạng thái(state).Để observer thì bạn dùng từ khoá asObservable.
+ BehaviorSubject : bắt đầu với giá trị khởi tạo và sẽ bắn kèm cho subscribe mới với 1 event gần nhất.
+ ReplySubject : giống behavior, và có thể para : buffersize để xác định số lập lại.
+ Variable : wrap một BehaviorSubject và lưu trữ giá trị như một trạng thái(state).Để observer thì bạn dùng từ khoá asObservable.
Sơ đồ sau sẽ giải thích cho các bạn rõ sự khác nhau.
-PublicSubject : bắt đầu rỗng và chỉ bắn ra event khi có subscribe, nó bỏ qua các phần tử đã bắn trc đó trước khi nhận 1 subscibe
//Khởi tạo 1 PublishSubject let subject = PublishSubject<String>()//Chuyển PublishSubject -> Observable let observable : Observable<String> = subject //Chưa có 1 subscribe nào -> onNext ko có tác động subject.onNext("bỏ qua") //Bắt đầy subscribe observable .subscribe(onNext: { text in print(text) }) .addDisposableTo(disposeBag) // Khi trong hàng đợi subscribe có ít nhất 1 cái subject.onNext("Start!")
-BehaviorSubject : bắt đầu với giá trị khởi tạo và sẽ bắn kèm cho subscribe mới với 1 event gần nhất.Chỉ nhận mới nhất và mới nhất gần nhất
let subjectBehavior = BehaviorSubject<String>(value: "Gia tri ban dau") let observable : Observable<String> = subjectBehaviorsubjectBehavior.onNext("event1") subjectBehavior.onNext("event2") subjectBehavior.onNext("event3") // mới nhất gần nhấtobservable .subscribe(onNext: { text in print(text) }) .addDisposableTo(disposeBag)subjectBehavior.onNext("event4") // mới nhất // event3 // event4
-ReplySubject : giống behavior, và có thể para : buffersize để xác định số lập lại ngoài cái mới nhất
// Định nghĩa ReplaySubject với số lần lặp lại là 2 let subjectReply = ReplaySubject<String>().create(bufferSize: 2) let observable : Observable<String> = subjectReplysubjectReply.onNext("event1") subjectReply.onNext("event2") // mới nhất lần 2 subjectReply.onNext("event3") // mới nhất lần 1observable .subscribe(onNext: { text in print(text) }) .addDisposableTo(disposeBag)subjectReply.onNext("event4") // mới nhất// event 2 // event 3 // event 4
-Variable
: wrap một BehaviorSubject, nó giống BehviorSubject ở chỗ sẽ bắt các
event mới nhất và gần mới nhất , lưu trữ giá trị như một trạng
thái(state).Variable có property value có thể gắn giá trị vào đó.Để
observer thì bạn dùng từ khoá asObservable.
let variable = Variable<Int>(0) print("Before first subscription ---")let variable1 = variable.asObservable() .subscribe(onNext: { n in print("First \(n)") }, onCompleted: { print("Completed 1") })print("Before send 1") variable.value = 1//Before first subscription --- //First 0 //Before send 1 //First 1
Ok
, phần này mình đã trình bày cho các bạn về Observable vs Subject trong
RXSwift. Trong phần sau minh sẽ nói về các toán tử (operator), giúp kết
hợp các observable theo các chức năng khác nhau.
Hãy follow để nhận thông báo bài viết mới nhấy nhé.
Comments
Post a Comment