[RxJava] Code gọn gàng hơn với doOnSubscribe, doFinally và doOnTerminate
Rx
7
RxJava
7
Male avatar

Hades viết ngày 07/03/2020

Introduction

Là 1 fan của RxJava, khi sử dụng tôi nhận thấy rằng rất nhiều trường hợp sử dụng với RxJava tuân theo cùng một flow từ việc setup đến khi kết thúc logic. Một ví dụ phổ biến là tải dữ liệu lên màn hình như sau :

  1. Hiển thị trạng thái đang Loading.
  2. Tải dữ liệu
  3. Khi dữ liệu được tải thành công rồi thì ẩn trạng thái loading đi và cập nhật UI.
  4. Hoặc khi có lỗi xảy ra, ẩn trạng thái loading đi và hiển thị lỗi.

OK, vậy khi thể hiện trong code nó sẽ như nào ?

fun getDataFromServer() {

    view.showLoadingIndicator();

    loadFromServer()
            .compose(applySchedulers())
            .subscribe(data -> {
                view.hideLoadingIndicator();
                view.showData(data);
            }, error -> {
                view.hideLoadingIndicator();
                view.showError(error);
            });

    loadData()

}

Có lẽ bạn đã phát hiện ra điều gì đó rồi chứ, view.hideLoadingIndicator() bị gọi 2 lần. Có thể bạn thấy điều này không quá là vấn đề nhưng đây mới chỉ là ví dụ đơn giản mà việc hideLoading đã bị duplicate, với những trường hợp phức tạp hơn, việc hideLoading sẽ phải gọi nhiều lần trong chuỗi.
Có 2 lý do khiến mình không thích điều này :

  • view.showLoadingIndicator() bị out khỏi chuỗi mặc dù nó được gắn với logic.
  • Phần logic xử lý lỗi lại chứa code không xử lý lỗi.

How to resolve ?

Trong phần này, mình muốn giới thiệu 3 toán tử tiện lợi giúp cho code trở lên clean hơn :

  • doOnSubscribe() : sửa đổi nguồn source để nó gọi action được chỉ định ngay khi được subscribe.
  • doOnTerminate() : gọi action được chỉ định ngay trước khi Observable thông báo onError() hoặc onCompleted()
  • doAfterTerminate() : gọi hành động được chỉ định ngay sau khi Observable rơi vào onError() hoặc onCompleted()
  • doFinally() : gọi hành động được chỉ định sau khi Observable rơi vào onError() hoặc onCompleted() hoặc bị disposed bởi downstream.

Áp dụng những điều này cho ví dụ trên, kết quả sẽ như sau :

fun getDataFromServer() {

    loadFromServer()
            .compose(applySchedulers())
            .doOnSubscribe(__ -> view.showLoadingIndicator())
            .doOnTerminate(() -> view.hideLoadingIndicator())
            .subscribe(data -> {
                view.showData(data);
            }, error -> {
                view.showError(error);
            });

    loadData();

}

Thay đổi nhỏ, nhưng nhìn đã clean hơn kha khá rồi phải không :D
Có bạn thắc mắc tại sao mình sử dụng doOnTerminate() thay vì doFinally() ?

=> Bởi vì trong trường hợp này, mình dispose observable sau khi screen bị destroy do đó mình không gọi các thao tác UI trong trường hợp này.

Conclusion

Hi vọng bài viết này giúp bạn đánh giá cao lợi ích mà những thay đổi nho có thể mang lại.
Happy coding !!!

Reference

Bình luận


White
{{ comment.user.name }}
Bỏ hay Hay
{{comment.like_count}}
Male avatar
{{ comment_error }}
Hủy
   

Hiển thị thử

Chỉnh sửa

Male avatar

Hades

14 bài viết.
16 người follow
Kipalog
{{userFollowed ? 'Following' : 'Follow'}}
Cùng một tác giả
Male avatar
9 13
Dưới đây là một cách tổ chức thư mục mà mình cho là khá hợp lý. Hi vọng mọi người có thể tham khảo và góp ý :smile: Android_structure ├─ com.abc ...
Hades viết gần 4 năm trước
9 13
Male avatar
5 2
Những điều cần nhớ Hades 22042017 Đừng dùng lại Đừng sử dụng lại strings cho nhiều màn hình khác nhau. 1. Tưởng tượng rằng bạn có một hộp thoạ...
Hades viết hơn 3 năm trước
5 2
Male avatar
4 0
Giới thiệu RecycleView là một viewGroup mới được giới thiệu trong Android L ( API 21 ). Đây là một viewGroup có chức năng tương tự như ListView nh...
Hades viết gần 4 năm trước
4 0
Bài viết liên quan
Male avatar
0 0
Introduction Hi ae, trong bài viết này, mình sẽ cùng các bạn tìm hiểu về cách xử lý lỗi trong RxJava. Đầu tiên, hãy nhớ rằng Observable thường kh...
Hades viết 3 tháng trước
0 0
Male avatar
0 0
Introduction Hi mọi người, hôm nay chúng ta sẽ cùng tìm hiểu một số operator đơn giản và hữu ích trong Rx là Concat và Merge nhé. Concat() (Ảnh...
Hades viết 7 tháng trước
0 0
{{like_count}}

kipalog

{{ comment_count }}

bình luận

{{liked ? "Đã kipalog" : "Kipalog"}}


Male avatar
{{userFollowed ? 'Following' : 'Follow'}}
14 bài viết.
16 người follow

 Đầu mục bài viết

Vẫn còn nữa! x

Kipalog vẫn còn rất nhiều bài viết hay và chủ đề thú vị chờ bạn khám phá!