ReactiveX Java / Android – First Tale

Mở đầu

RxJava là một thư viện dùng để phục vụ cho việc xử lý đa tiến trình, dựa theo Observer Design Pattern. RxJava là một phần trong bộ công cụ ReactiveX (có trên .NET, C++, JavaScript, nhiều ngôn ngữ khác).

Để giúp các bạn dễ hình dung về tính năng của nó, ở đây tôi sẽ nêu ra một số ví dụ để các bạn có thể hiểu và sử dụng được RxJava trong ứng dụng Android của mình.
Các ví dụ sẽ được đăng tải lên Github dưới dạng project Android có thể compile và chạy được.

Observer Pattern và Reactive

Về cơ bản, có thể tóm gọn về Observer Pattern như sau: Một bên làm Observable (ví dụ: server), các bên còn lại đăng ký vào Observable (ví dụ: client), lúc này các client được gọi là các Observers. Mỗi khi Observable thay đổi, các Observers sẽ nhận được “tín hiệu thay đổi” đã đăng ký từ trước.

Điều này cũng giống cơ chế Twitter hoạt động: A follow B, nếu B có tweet mới thì A sẽ nhận được thông báo. Lúc này B là Observable còn A là Observer (đúng ra server Twitter mới là Observable, nhưng thôi cứ lấy ví dụ như này cho dễ hiểu).

Các Observers sẽ có phản ứng lại mỗi khi Observable “emit” (truyền) tín hiệu, hoặc báo lỗi, hoặc không còn gì để truyền nữa (xong rồi). 3 phương thức tương ứng là onNext(), onError(), và onCompleted().

View at Medium.com
View at Medium.com

Đầu tiên: Lập trình có tính phản ứng (Reactive Programming) là gì?
Và sau khi đọc câu hỏi trên thì nhiều bạn sẽ google từ khóa trên, cả tiếng Anh lẫn tiếng Việt đều giải thích đại khái là:

Reactive programming is programming with asynchronous data streams.
(Reactive Programming là lập trình với luồng dữ liệu bất đồng bộ)

Từ từ, thế thì dùng cơ chế callback cũng làm được bình thường, khái niệm này không mới, và code thì thường được viết dưới dạng tường minh (imperative) như kiểu callback vừa đề cập.

Ấy thế nhưng trong quá trình làm việc, bạn sẽ gặp trường hợp dạng như sau:

Android không cho phép thực hiện networking task trên UI Thread (thread chạy giao diện), do đó ta phải thực hiện bất đồng bộ. Nhưng nếu dữ liệu của chúng ta cần nằm ở site C, địa chỉ site C phải truy vấn từ site B, địa chỉ site B phải truy vấn từ site A. Lúc này ta chỉ có địa chỉ của website A. Với cơ chế callback, giả sử trường hợp bèo nhèo nhất là có duy nhất 1 callback, tôi tạm gọi là onCompleted(String data). Vậy thì cũng phải qua 3 lần xử lý. nếu chưa hình dung ra thì các bạn xem đoạn code dưới:

[java] // Vòng 1:
loadDataFromNetwork(final String url, new NetworkCallback {
@Override
protected void onCompleted (String returnedData){

}
});
[/java]

Rồi nhé, onCompleted tức là sau khi download data xong thì nó sẽ trả về đoạn String data, String này chính là url để vào vòng trong nữa, và cứ thế, cứ thế, như này:

[java] // Vòng 1:
loadDataFromNetwork(final new NetworkCallback {
@Override
protected void onCompleted (String returnedData){
// Vòng 2:
loadDataFromNetwork(final String returnedData, new NetworkCallback {
@Override
protected void onCompleted (String returnedData){
// Và cứ thế cho đến vòng n…
}
});
}
});
[/java]

Đấy, đây mới là trường hợp bèo nhèo khi chỉ cần xử lý 1 hàm onCompleted, mà thường là ta phải xử lý cả trường hợp onError on gì gì nữa để còn báo cho người dùng (ví dụ: không có wifi, không có 3G, máy chủ chết,…). Vấn đề này gọi là callback hell, thường gặp trong các tác vụ xử lý bất đồng bộ.

Và như vậy, người ta đã tìm ra giải pháp là Reactive, là sự kết hợp của 3 thứ: Observer Pattern, Iterator PatternFunctional Programming.

Stream

Trong FRP, mọi thứ đều là Stream:

– Một biến bình thường? Stream.
– Một event click chuột? Stream.
– Một hành vi người dùng bất kỳ? Cũng có thể là Stream.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.