Sử dụng RxJava, RxAndroid và Retrolamda
Bài đăng này đã không được cập nhật trong 8 năm
Reactive Programming
là lập trình với các dòng dữ liệu bất đồng bộ. Sau khi đọc hàng chục bài viết, cày nát hàng trăm đoạn mô tả định nghĩa thì cuối cùng mình cũng "chưa hiểu gì". Tất cả những gì mình biết về Reactive Programming
chỉ có vậy (facepalm).
Đọc bài chán quá nên mình chuyển hướng sang thực hành và có lẽ nhờ nó minh sẽ giác ngộ ra chân lý cũng nên (haha) . Dù sao thì tuy không hiểu lý thuyết nhưng có làm thực hành vẫn hơn là không làm gì cả.
Bài này mình ghi lại những ví dụ khi làm việc với RxJava
, RxAndroid
và Retrolambda
để xem cách nó hoạt động ra sao.
Các thành phần cơ bản của Rx Programming đó là Observerables
và Subscribers
. Một Observerable
phát ra các items, một Subscriber lắng nghe và xử lý các items đó khi nó được phát ra.
CÀI ĐẶT
Trước hết bạn muốn làm việc với Lambda Expression
trên Android studio bạn phải cài đặt Retrolambda
theo bài viết này.
Sau đó cài đặt RxJava
và RxAndroid
bằng gradle dependencies:
compile 'io.reactivex:rxandroid:1.1.0'
compile 'io.reactivex:rxjava:1.1.0'
Thêm nữa để làm việc với View thì bạn cần thêm dependency của thư viện RxBinding
compile 'com.jakewharton.rxbinding:rxbinding:0.3.0'
Bạn sync lại gradle và bắt đầu viết thử một số đoạn mã nào.
View Click Event
RxBinding là thư viện hỗ trợ giúp viết các sự kiện theo cách của Reactive Programming
.
Thay vì bạn bắt sự kiện click của một Button bằng cách thông thường
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
thì bạn có thể dùng RxView
của RxBinding
:
RxView.clicks(fab)
.subscribe(v->Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null)
.show());
Filter số chẵn
Observable.just(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
.filter(i -> i % 2 == 0)
.subscribe(i -> Log.v("Result", "Even Numbers = [ " + i + " ]"));
Observerable
cung cấp method just()
dùng để convert các objects, lists, mảng objects, vào các Observerables
và phát ra các objects đó.
Kết quả khi bạn xem logcat sẽ như sau:
01-24 20:52:25.069 31326-31326/com.framgia.lupx.rxexample V/Result: Even Numbers = [ 2 ]
01-24 20:52:25.069 31326-31326/com.framgia.lupx.rxexample V/Result: Even Numbers = [ 4 ]
01-24 20:52:25.069 31326-31326/com.framgia.lupx.rxexample V/Result: Even Numbers = [ 6 ]
01-24 20:52:25.069 31326-31326/com.framgia.lupx.rxexample V/Result: Even Numbers = [ 8 ]
01-24 20:52:25.069 31326-31326/com.framgia.lupx.rxexample V/Result: Even Numbers = [ 10 ]
Lặp với forEach
Observable.just(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
.forEach(i -> Log.v("Iterating", "" + i));
Kết quả:
01-24 21:06:02.466 8438-8438/com.framgia.lupx.rxexample V/Iterating: 1
01-24 21:06:02.466 8438-8438/com.framgia.lupx.rxexample V/Iterating: 2
01-24 21:06:02.466 8438-8438/com.framgia.lupx.rxexample V/Iterating: 3
01-24 21:06:02.466 8438-8438/com.framgia.lupx.rxexample V/Iterating: 4
01-24 21:06:02.466 8438-8438/com.framgia.lupx.rxexample V/Iterating: 5
01-24 21:06:02.466 8438-8438/com.framgia.lupx.rxexample V/Iterating: 6
01-24 21:06:02.466 8438-8438/com.framgia.lupx.rxexample V/Iterating: 7
01-24 21:06:02.466 8438-8438/com.framgia.lupx.rxexample V/Iterating: 8
01-24 21:06:02.466 8438-8438/com.framgia.lupx.rxexample V/Iterating: 9
01-24 21:06:02.466 8438-8438/com.framgia.lupx.rxexample V/Iterating: 10
Thực hiện GroupBy
Observable.just(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
.groupBy(i -> i % 2 == 0)
.subscribe(grouped ->
grouped.toList()
.subscribe(integers -> {
Log.v("Result", integers + "Even(" + grouped.getKey() + ")");
}));
Kết quả:
01-24 21:18:42.838 19088-19088/com.framgia.lupx.rxexample V/Result: [1, 3, 5, 7, 9]Even(false)
01-24 21:18:42.838 19088-19088/com.framgia.lupx.rxexample V/Result: [2, 4, 6, 8, 10]Even(true)
Chọn N phần tử đầu tiên
Observable.just(1,2,3,4,5,6,7,8,9,10)
.take(5)
.subscribe(i->Log.v("Result",""+i));
Kết quả:
01-24 21:23:52.080 22941-22941/com.framgia.lupx.rxexample V/Result: 1
01-24 21:23:52.080 22941-22941/com.framgia.lupx.rxexample V/Result: 2
01-24 21:23:52.080 22941-22941/com.framgia.lupx.rxexample V/Result: 3
01-24 21:23:52.080 22941-22941/com.framgia.lupx.rxexample V/Result: 4
01-24 21:23:52.080 22941-22941/com.framgia.lupx.rxexample V/Result: 5
First
Observable.just(1,2,3,4,5,6)
.first().subscribe(i->Log.v("Result",""+i));
Kết quả: Result: 1
Last
Observable.just(1,2,3,4,5,6)
.last().subscribe(i->Log.v("Result",""+i));
Kết quả: Result: 6
Distinct
Observable.just(1,2,3,1,2,3,1,2)
.distinct()
.subscribe(i->Log.v("Result",""+i));
Kết quả thu được 3 số 1,2,3
01-24 21:31:08.465 28400-28400/com.framgia.lupx.rxexample V/Result: 1
01-24 21:31:08.465 28400-28400/com.framgia.lupx.rxexample V/Result: 2
01-24 21:31:08.465 28400-28400/com.framgia.lupx.rxexample V/Result: 3
Map
Toán tử map() giống như là phép ánh xạ trong toán học. Giả sử mình dùng phép bình phương.
Observable.just(1,2,3,4)
.map(i->i*i)
.subscribe(i->Log.v("Result",""+i));
Kết quả thu được lần lượt các số 1,4,9,16
Bạn có thể sử dụng phép map nữa để convert ngược lại giá trị ban đầu
Observable.just(1,2,3,4)
.map(i->i*i)
.map(i->Math.sqrt(i))
.subscribe(i->Log.v("Result",""+i));
Kết quả là : 1,2,3,4
Tạm thời mình giới thiệu một số method mình hiểu thế đã. Mình sẽ cập nhật thêm các method khác và sẽ viết 1 bài chi tiết về Reactive Programming
với RxJava, RxAndroid khi nào mình hiểu về nó. (haha)
Github: RxExample
All rights reserved