+2

Bài 2. RxSwift – Observables

1. Observables

Đây là phần trung tâm của RxSwift. Observable chính là trái tim của cả hệ thống. Nó là nơi mà các thành phần khác có thể quan sát được. Nó tác động trực tiếp tới giao diện của bạn, dựa vào những gì mà nó phát ra cho bạn.

1.1. Khái niệm

Khi tìm hiểu về RxSwift hay Rx nói chung, bạn sẽ nghe tới các khái niệm observable, observable sequence hay đơn giản là sequence. Khá là mơ hồ nhưng tất cả chúng đều là một và ám chỉ tới nguồn phát. Khác nhau ở góc độ mà họ muốn mình hiểu.

  • Observable : là nguồn phát ra dữ liệu mà các đối tượng khác có thể quan sát được và đăng ký tới được.
  • Sequence : là luồng dữ liệu được nguồn phát phát đi. Vấn đề quan trọng, bạn cần hiểu nó như 1 Array, nhưng chúng ta không thể lấy hết 1 lúc tất cả các giá trị của nó. Và chúng ta không biết nó lúc nào kết thúc hay lúc nào lỗi …

1.2. Marble Diagrams

Sử dụng marble diagrams để mô tả sự hoạt động của nguồn phát. Bạn vào trang này để xem https://rxmarbles.com/. Ví dụ: image.png

Với 1 biểu đồ thì bao gồm như sau:

Bắt đầu từ trái sang phải Các giá trị phát ra là các số được vòng tròn & tô màu lại Dấu | biểu tượng cho kết thúc (completed) Dấu X biểu tượng cho lỗi (error)

2. Vòng đời Observables

Cuộc đời của một Observable rất chi là đơn giản. Nó chỉ có một nhiệm vụ là bắn những gì mà nó có đi thôi. Nên cuộc đời nó sẽ xoay quanh giá trị và nó bắn đi. Với 3 kiểu giá trị mà 1 Observable được phép bắn đi như sau:

  • Value : chính là giá trị dữ liệu nguồn phát phát đi (hay còn gọi là emit ).
  • Error: là lỗi khi có gì đó sai sai trong quá trình hoạt động. Sau đó nó cũng tự kết thúc.
  • Completed: kết thúc cuộc đời.

image.png

Thông qua 3 giá trị đó thì mô tả cuộc đời Observable như sau:

  • Khởi tạo Observable
  • Cứ onNext là sẽ phát giá trị đi
  • Quá trình này cứ lặp đi lặp lại cho tới khi
    • Hết thì sẽ là completed
    • Lỗi thì sẽ là error
  • Khi khi đã completed hoặc error thì Observable không thể phát ra được gì nữa –> kết thúc

3. Cách tạo Observables (cơ bản)

Ví dụ chúng ta có đoạn code sau:

let iOS = 1
let android = 2
let flutter = 3

just

let observable1 = Observable<Int>.just(iOS)

Trong đó:

  • observable1 là biến kiểu Observable
  • Int là kiểu dữ liệu cho Output của Observable
  • just là toán tử để tạo ra 1 observable sequence với 1 phần tử duy nhất

image.png

Tại sao là just? Thì cái tên này cũng nói lên tất cả rồi. Nó sẽ tạo ra 1 Observable và phát đi 1 giá trị duy nhất. Sau đó, nó sẽ kết thúc.

of

let observable2 = Observable.of(iOS, android, flutter)
  • Ta thấy đối tượng Observable lần này sử dụng toán tử of
  • Không cần khai báo kiểu dữ liệu cho Output
  • Thư viện tự động nội suy ra kiểu dữ liệu từ các dữ liệu cung cấp trong of(.....) Một ví dụ khác:
let observable3 = Observable.of([iOS, android, flutter])

from

let observable4 = Observable.from([iOS, android, flutter])

Khác với of:

  • from cần truyền vào một array
  • kiểu dữ liệu cho biến observalbe4 là Observable<Int> image.png

4. Subscribing to Observables

Với RxSwift, bạn có thể xem các dữ liệu mà Observable phát ra. Nó cũng là 1 sequence trình tự lần lượt phát đi các phần tử.

Subscribe

observable1.subscribe { event in
        print(event)
}

Trở lại ví dụ trên chúng ta đã có observable1, giờ chúng ta gọi toán tử .subscribe. Để handle dữ liệu nhận được, chúng ta cung cấp cho nó 1 closure. Trong closure, chỉ có in giá trị ra thôi. Kết quả như sau:

next(1)
completed

Thử với observable2:

observable2.subscribe { event in
    if let element = event.element {
        print(element)
      }
}

Kết quả cho ra:

1
2
3

Như kết quả trên, chúng ta đã không còn thấy nextcompleted

Handle events

Nếu bạn cần lấy thêm các sự kiện error hay completed thì hãy xem ví dụ dưới đây.

  • Dành cho onNext
observable3.subscribe(onNext: { element in
      print(element)
})
  • Full options
observable4.subscribe(onNext: { (value) in
        print(value)
    }, onError: { (error) in
        print(error.localizedDescription)
    }, onCompleted: {
        print("Completed")
    }) {
        print("Disposed")
    }

Với các Full options thì bạn bắt được hết các kiểu event với đầy đủ 3 kiểu giá trị mà Observable có thể phát ra. Đối với mỗi loại, bạn xử lý bằng việc phải cung cấp một closure cho nó. Và bạn có thể bỏ bớt đi các handle không cần thiết. Như chỉ quan tâm tới onNext và onCompleted thôi.

observable4.subscribe(onNext: { (value) in
        print(value)
    }, onCompleted: {
        print("Completed")
    })

Về Disposed thì mình sẽ đề cập ở các phần sau.

5. Các dạng đặc biệt của Observables

Empty

Đây là toán tử mà nó tạo ra 1 Observable. Observable này đặc biệt là không phát ra phần tử nào hết và nó sẽ kết thúc ngay.

Ví dụ, chạy thử đoạn code sau:

   let observable = Observable<Void>.empty()
    
    observable.subscribe(
      onNext: { element in
        print(element)
    },
      onCompleted: {
        print("Completed")
      }
    )

Never

Cùng làm thử ví dụ sau:

let observable = Observable<Any>.never()
    
    observable.subscribe(
        onNext: { element in
            print(element)
        },
        onCompleted: {
            print("Completed")
        }
    )

Kết quả chúng ta thấy không có gì ở đây được phát và được nhận hết.

Toán tử .empty nó khác với .never. Never thì sẽ không phát ra gì cả và cũng không kết thúc luôn.

Range

image.png

Chúng ta cùng demo đoạn code sau:

let observable = Observable<Int>.range(start: 1, count: 10)
    var sum = 0
    observable
        .subscribe(
            onNext: { i in
                sum += i
        } , onCompleted: {
            print("Sum = \(sum)")
        }
    )

Nó giống như một vòng for đơn giản. Observable với kiểu phần tử được phát đi là Int. Chúng sẽ phát ra lần lượt, số lần phát chính là count và giá trị bắt đầu phát ra là start. Sau mỗi lần phát thì start sẽ được tăng lên 1 đơn vị.

Tham khảo:

https://fxstudio.dev/rxswift-observables/


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí