07/09/2018, 17:09

RxSwift: Bài 3 - Disposing and terminating

RxSwift: Bài 3 - Disposing and terminating 1. Đặt vấn đề: Nhắc lại là 1 observable sẽ không làm bất kì điều gì cho đến khi nó nhận một subscribe. Cái việc subscription này sẽ trigger hay báo hiệu cho một observable để bắt đầu phát ra các events, cứ thế cho đến khi nó phát ra sự kiện .error ...

RxSwift: Bài 3 - Disposing and terminating

1. Đặt vấn đề:
Nhắc lại là 1 observable sẽ không làm bất kì điều gì cho đến khi nó nhận một subscribe. Cái việc subscription này sẽ trigger hay báo hiệu cho một observable để bắt đầu phát ra các events, cứ thế cho đến khi nó phát ra sự kiện .error hoặc .completed rồi mới xong. Thực tế thì ta có thể làm việc này thủ công để khiến cho observable phải kết thúc bằng cách kết thúc tất cả các subscribe.

Vẫn trong ví dụ của bài 1, 2, ta thêm đoạn code sau:
alt text

Trình tự các bước như sau:

  1. Tạo ra một observable của một vài strings.
  2. Subscribe thằng observable này, lần này ta sẽ lưu cái biến trả về Disposable cho 1 local constant (đặt tên là subscription)
  3. Print ra các emit trong cái handler.
  4. Để cancel đàng hoàng một subscription, gọi dispose() nó là được. Sau khi cancel cái subscription này (hay nói cách khác là dispose nó), cái observable này hiện tại sẽ ngưng emit ra các events.

Quản lí từng subscription riêng biệt nhìn khá nghiệp dư nên RxSwift đã có thêm cho ta 1 cái gọi là DisposeBag. Cái này dễ giữ các disposables, mà được add trong dispose(to: DisposeBag), và nó sẽ gọi dispose() mỗi khi subscribe này chuẩn bị deallocated.
alt text

Dưới đây là cách mà disposable code hoạt động:

  • Tạo ra một disposeBag
  • Tạo ra một observable
  • Subscribe đến observable và print out ra cái giá trị được emit
  • Add cái giá trị disposable đc trả về vào cái disposeBag

Đây là pattern bạn sẽ dùng rất nhiều: Tạo ra observable rồi subscribe nó và add cái subscription vào 1 disposeBag

Tại sao lại lo lắng về vấn đề này ? Nếu bạn quên add cái subscription vào dispose bag hay add nó bằng manual hay cách nào khác khiến cho observable kết thúc ở nhiều chỗ khác nhau dẫn đến leak memory.

2. Create operator
Có một cách để lôi ra các events mà observable sẽ emit đến subscribers là create operator.
alt text
Ở đây take note 1 chút về return Disposable, Disposables.create() là một empty disposable để ai subscribe sẽ có disposable mà trả về.
Trước hết, ta xem thử create có gì trong đó:
alt text

Cái create operator này sẽ nhận 1 parameter là subscribe, nhiệm vụ của nó là tiến hành gọi observable. Hay nói cách khác, nó defines các event mà sẽ được emit đến subscribers. Subscribe này là 1 escaping closure mà lấy 1 AnyObserver và trả về 1 Disposable.

AnyObserver là 1 generic type giúp cho việc add các giá trị này vào observable sequence được dễ dàng hơn, và chúng sau đó sẽ được emit đến các subscribers

The subscribe parameter is an escaping closure that takes an AnyObserver and returns a Disposable. AnyObserver is a generic type that facilitates adding values onto an observable sequence, which will then be emitted to subscribers. Change the implementation of create to the following:

Nhìn vào các đoạn code trên, bạn xem thử liệu onNext(?) có được gọi không? Dĩ nhiên là không, bởi vì observable đã phát ra .completed event. Ta check thử bằng cách sau:
alt text

Và kết quả sẽ là:
alt text

3. Trường hợp leak memory
Bây giờ, giả sử ta có lỗi thì sao? Add 1 enum ở ngoài class như sau:
alt text

Sau đó add thêm error giữa onNext và onComplete
alt text

Kết quả sẽ là:
alt text

Rõ ràng bạn thấy nó gọi Error ra và kết thúc, onCompleted không hề được gọi trong trường hợp này.

Bây giờ ta giả sử bạn ko có hàm onError và onCompleted cũng như không có disposeBag thì chuyện gì sẽ xảy ra ?
alt text

Kết quả là observable không bao giờ kết thúc và disposable cũng không bao giờ bị disposed dẫn đến tình trạng memory leak
alt text

Như vậy mình đã kết thúc bài 3. Cảm ơn mn đã theo dõi

0