12/08/2018, 16:24

RxJava: Sự khác biệt giữa Flatmap, SwitchMap, ConcatMap

Chào mọi người, chắc hẳn khi các bạn sử dụng Rx đều biết đến một số các phương thức để chuyển đổi từ Observable dạng này sang một Observable dạng khác, mà phương thức đầu tiên ta biết hẳn là FlatMap. Nhưng ngoài ra, Rx còn cung cấp cho ta một số các phương thức khác như SwitchMap, ConcatMap. Vậy ...

Chào mọi người, chắc hẳn khi các bạn sử dụng Rx đều biết đến một số các phương thức để chuyển đổi từ Observable dạng này sang một Observable dạng khác, mà phương thức đầu tiên ta biết hẳn là FlatMap. Nhưng ngoài ra, Rx còn cung cấp cho ta một số các phương thức khác như SwitchMap, ConcatMap.

Vậy chúng có gì khác biệt và được dùng trong trường hợp nào, hãy cùng tìm hiểu nhé!

Đầu tiên hãy bắt đầu với một đoạn Java Unit test để chạy thử flatMap. Đầu tiên ta tạo ra một list String, sau đó sẽ chuyển đổi mỗi phần tử trong list đó thành một Observable sử dụng operator from. Mỗi phần tử sau khi được map vào Observable sẽ được cộng thêm với chữ "x" ở cuối. Tiếp theo mỗi Observable sẽ delay một khoảng random từ 0 - 10s. Cuối cùng ta cộng thêm thời gian chạy 1 phút để chắc chắn tất cả các phần tử đã đượt phát ra(emit). (Nếu không làm vậy, bài test có thể kết thúc trước khi toàn bộ các phần tử được emit.)

Chuyển sang code:

@Test
public void flatMap() throws Exception {
    final List<String> items = Lists.newArrayList("a", "b", "c", "d", "e", "f");

    final TestScheduler scheduler = new TestScheduler();

    Observable.from(items)
            .flatMap( s -> {
                final int delay = new Random().nextInt(10);
                return Observable.just(s + "x")
                        .delay(delay, TimeUnit.SECONDS, scheduler);
            })
            .toList()
            .doOnNext(System.out::println)
            .subscribe();

    scheduler.advanceTimeBy(1, TimeUnit.MINUTES);
}

Sau khi chạy thử, kết quả là [cx, ex, fx, bx, dx, ax]

Ồ, bạn có thấy gì lạ không, các phần tử của list sau khi được flatMapped thì đã không theo thứ tự như trước nữa. Hãy đọc thử phần docs của FlatMap bạn sẽ rõ:

Note that FlatMap merges the emissions of these Observables, so that they may interleave.

Mình tạm giải thích đó là Operator flatMap sẽ không quan tâm đến thứ tự của các phần tử. Nó sẽ tạo một Observable mới cho mỗi phần tử và không liên quan gì đến nhau. Có phần tử sẽ emit nhanh, có phần tử emit chậm bởi vì trước đó mình đã tạo một đoạn delay ngẫu nhiên cho các phần tử.

Với cùng bài test trên, mọi thứ được giữ nguyên, chỉ thay đổi Operator flatMap thành switchMap và xem điều gì xảy ra nhé:

@Test
public void switchMap() throws Exception {
    final List<String> items = Lists.newArrayList("a", "b", "c", "d", "e", "f");

    final TestScheduler scheduler = new TestScheduler();

    Observable.from(items)
            .switchMap( s -> {
                final int delay = new Random().nextInt(10);
                return Observable.just(s + "x")
                        .delay(delay, TimeUnit.SECONDS, scheduler);
            })
            .toList()
            .doOnNext(System.out::println)
            .subscribe();

    scheduler.advanceTimeBy(1, TimeUnit.MINUTES);
}

Kết quả: [fx]

Xem kết quả bạn cũng hiểu rồi đúng không             </div>
            
            <div class=

0