Những chủ đề nóng nhất trong giới Android Developer năm qua. Tuy nhiên có một vấn đề duy nhất là bạn có thể gặp khó khăn khi tiếp cận lúc ban đầu. Functional Reactive Programming khá là khó làm quen khi bạn đến từ thế giới Imperative, nhưng một khi bạn hiểu nó, nó thật tuyệt vời!
Ở đây tôi sẽ cố gắng cung cấp cho các bạn một số kiến thức cơ bản về RxJava. Tôi sẽ không giải thích tất cả mọi thứ (thực ra là tôi không thể :d ). Tôi chỉ muốn giúp bạn hứng thú với RxJava và chỉ ra cách mà nó hoạt động.
Khái niệm cơ bản
Reactive code gồm 2 phần cơ phản là Observables và Subscribers. Observables phát ra các items, Subscriber tiếp nhận và sử dụng các items đó.
Một Observable có thể phát ra bất kỳ số lượng các items, sau đó nó chấm dứt, hoặc bằng cách thành công (successfully completing), hoặc xảy ra lỗi (error). Đối với mỗi Subscriber nó có, một Observable gọi Subscriber.onNext() số lần bất kỳ , tiếp theo sẽ là một trong một trong hai hàm Subscriber.onComplete () hoặc Subscriber.onError() sẽ được gọi.
Điều này rất giống standard observer pattern ,nhưng nó có một sự khác biệt – Observables thường không bắt đầu phát ra các items cho đến khi có Subscriber lắng nghe nó.
Hello, World
Hãy xem một ví dụ cụ thể. Trước tiên, hãy tạo ra một Observable. cơ bản .
Observable của chúng ta phát ra String “Hello, world!” sau đó hoàn tất. Bây giờ hãy tạo một Subscriber để nhận dữ liệu:
Tất cả điều này làm là in mỗi chuỗi phát ra bởi Observable.
Bây giờ chúng ta đã có myObservable và mySubscriber chúng ta có thể nối chúng với nhau bằng cách sử dụng phương thức subscribe().
Khi subscription được tạo ra, myObservable sẽ gọi phương thức onNext ()và onComplete của subscriber.Kết quả là, mySubscriber sẽ cho ra output “Hello, world!” sau đó chấm dứt.
Simpler Code
Trên đây là rất nhiều mã boilerplate chỉ để in ra ” Hello, world!”
Đó là bởi vì tôi đã là con đường dài, do đó bạn có thể thấy chính xác những gì đang xảy ra. Có rất nhiều cách được cung cấp trong RxJava đểviệc viết code trở nên dễ dàng hơn.
Đầu tiên, chúng ta hãy đơn giản hóa Observable của chúng ta. RxJava có tích hợp nhiều cách để tạo ra Observable cho những trường hợp thường gặp. Trong trường hợp này, Observable.just () phát ra một item duy nhất sau đó hoàn thành, giống như code của chúng ta ở trên :
Tiếp theo, hãy xử lý những cái không cần thiết trong Subscriber .Chúng ta không quan tâm về onCompleted ()hay onError(),vì vậy chúng ta có thể sử dụng một class đơn giản để xác định những việc cần làm trong onNext():
Observable.subscribe () có thể xử lý một, hai hoặc ba Action thay thế cho onNext(), onError(),và onComplete().Thay thế cho Subscriber của chúng ta bên trên sẽ được như này :
Tuy nhiên, chúng ta chỉ cần tham số đầu tiên, bởi vì chúng ta đang bỏ qua onError () và onComplete():
Hoặc có thể viết code như sau
Cuối cùng, chúng ta hãy sử dụng Java 8 lambdas để cho code đẹp hơn
Nếu bạn code Android (và do đó không thể sử dụng Java 8), Tôi khuyên bạn nên sử dụng retrolambda; nó sẽ làm code của của bạn dễ nhìn hơn, gọn gàng đi rất nhiều.
Transformation
Giả sử tôi muốn thêm phần chữ ký của tôi ở phần output “Hello, world!”. Có một cách là thay đổi Observable:
Cách này bạn có thể thay đổi thông qua Observable,nhưng nó không đảm bảo thoả mãn tất cả các trường hợp – nếu tôi sử dụngcủa tôi Observable ở nhiều nơi nhưng chỉ một số chỗ tôi muốn thêm chữ ký?:
Bạn nghĩ sao về việc sửa ở Subscriber :
Câu trả lời này cũng không thoả mãn, vì các lý do khác nhau: tôi muốn Subscribers của tôi phải được làm nhẹ càng tốt vì tôi có thể chạy chúng trên mainthread.
Sẽ tốt hơn nếu tôi có thể thay đổi String “Hello, world!” với một số bước trung gian.
Introducing Operators
Operators có thể được sử dụng giữa Observable nguồn và các Subscriber để control các items được phát ra. RxJava đi kèm với một bộ sưu tập lớn Operators, nhưng tốt nhất của tôi sẽ tập trung vào chỉ một số đơn giản trước:
Đối với bài toán của chúng ta , map() operator có thể được sử dụng để chuyển đổi một item được phát ra:
Một lần nữa, chúng ta có thể đơn giản hóa code này bằng cách sử dụng lambdas
Khá cool phải không? map() operator của chúng ta cơ bản là một Observable biến đổi một item. Chúng ta có thể gọi nhiều map() operator liên tiếp nếu muốn chuyển đổi data trước khi nó đến Subscriber.
More on map()
Dưới đây là một khía cạnh thú vị của map (); nó không phải phát ra các item kiểu tương tự như Observable nguồn.
Giả sử Subscriber của tôi không quan tâm đến xuất ra text ban đầu, nhưng thay vào đó in ra mã băm của text:
Thật thú vị phải không ạ – chúng ta bắt đầu với một String nhưng Subscriber của chúng ta nhận được một Integer. Một lần nữa, chúng ta có thể sử dụng lambdas để rút ngắn code bằng
Giống như tôi đã nói bên trên , chúng ta muốn Subscriber của chúng ta làm càng ít càng tốt. Hãy thêm vào một map() để chuyển đổi mã băm của chúng ta trở thành một String:
Chúng ta thậm chí có thể thêm chữ ký của tôi trước khi chuyển đổi data:
So What
Tại thời điểm này, bạn có thể nghĩ “Đó là quá nhiều code cho một việc đơn giản” Đúng đó là một ví dụ đơn giản. Nhưng có hai ý tưởng bạn nên nghĩ tới:
Key 1 # Observable và Subscriber có thể làm bất cứ điều gì
Observable có thể là một database query, các Subscriber lấy kết quả và hiển thị chúng trên màn hình. Observable của bạn có thể là một stream dạng byte đọc từ internet, các Subscriber có thể ghi nó vào disk….
Key 2 # Các Observable và Subscriber độc lập với các bước chuyển đổi giữa chúng.
Tôi có thể gọi nhiều map() tôi muốn ở giữa Observable và Subscriber.Hệ thống này có tính composable cao. Chúng ta rất dễ dàng để thao tác với data.
Kết hợp hai ý tưởng chính của chúng ta có thể nhìn thấy một hệ thống với rất nhiều tiềm năng. Tại thời điểm này, vì chúng ta chỉ có một operator duy nhất map (),nên khả năng chúng ta đang bị giới hạn. Trong phần sau chúng ta sẽ tìm hiểu thêm nhiều operators mà RxJava cung cấp.
To be countinue!