+1

Sử dụng reactive pattern với LiveData trong ViewModel part II

I, Giới thiệu

  • Xin chào mọi người lại là mình đây. Ở bài viết lần trước, mình đã trình bày phần I của việc sử dụng reactive pattern của LiveData trong ViewModel.
  • Tưởng chừng như việc xử dụng LiveData sẽ rất đơn giản nhưng nó cũng sẽ có những bẫy mà chúng ta không ngờ tới.
  • Hiểu rõ và kỹ lưỡng cách sẽ giúp chúng ta implement 1 cách hoàn chỉnh và chính xác nhất.
  • Ở phần tiếp theo này, mình sẽ đưa ra các lỗi hay xảy ra khi xử dụng LiveData.

II. Nội dung

  1. Khi nào không nên sử dụng LiveData ?
  • Việc sử dụng LiveData là rất tốt bởi các thành phần của app được bound với nhau và tận dụng được lợi thế Lifecycle-aware.
  • Nhưng hãy cẩn thận không phải trường hợp nào bạn cũng áp dụng LiveData.
  • Lời khuyên: Nếu 1 thành phần của app không kết nối với UI, bạn không nên sử dụng LiveData.
  • Ví dụ: Trong app, bạn có 2 thành phần: User ManagerToken Uploader. User Manager sinh ra 1 token để upload lên server.

  • Câu hỏi đặt ra là nếu Token Uploader quan sát (observe) User Manager thì LifecycleOwner (LifecycleOwner được truyền vào onChange() method) sẽ là đối tượng nào ?
  • Chức năng upload token này không liên qua tới View.
  • Hơn thế nữa, nếu bạn cho LifecycleOwner trong View, thì khi View không ở trạng thái active, token có thể sẽ không được upload.
  • Giải pháp 1: Nếu observe không được, bạn có thể sử dụng observeForever() (nhận mọi event và sẽ không tự động bị remove) ở Token Uploader. Dựa vào Lifecycle trong User Manager mà bạn có thể remove việc observe khi token được upload. Giải pháp này có thể là 1 cách giải quyết nhưng chúng ta không cần thiết phải làm như vậy.
  • Giải pháp 2: Đơn giản chúng ta chỉ cần để User Manager tác động Token Uploader upload token 1 cách trưc tiếp.

  1. Antipattern: sharing instances of LiveData
  • Khi 1 class hiển thị LiveData cho 1 class khác, hãy suy nghĩ cẩn thận rằng bạn muốn hiển thị cùng 1 instance hay nhiều instance.
  • Ví dụ:

  • Nếu SharedLiveDataSource là singleton class, có phải luôn luôn chỉ có 1 instance của result không ?
  • Câu trả lời là không. Có những trường hợp sẽ cho ra nhiều instance của result.

  • Gọi 2 phương thức trên bạn sẽ gặp phải lỗi. Observer (userId = 1) có thể nhận update với data thuộc về userId = 2. Do 2 method đều chỉ update cùng 1 instance của result.
  1. Mediator smell: adding sources outside initialization
  • Sử dụng observer pattern là an toàn hơn việc bạn giữ reference của View ( cái mà MVP vẫn còn trong MVP).
  • Tuy nhiên vẫn có trường hợp có thể gây leak:
  • Mỗi lần bạn gọi addSource() method, bạn lại thêm 1 source vào trong destination.
  • Nhưng những source đã không còn được sử dụng không bị remove đi dẫn đến leak bộ nhớ.
  • Chú ý: Transformation.switchMap sẽ thêm 1 source và tự động remove source cũ khi thêm source mới nên các bạn không phải lo lắng về việc leak bộ nhớ.
  1. Transformation smell: Transformation outside initilization
  • Tranforamtion.mapTransformation.switchMap tạo ra 1 instance của randomNumber mỗi lần gọi.
  • Nếu việc theo dõi xảy ra ở onCreate() của View, sau đó mỗi lần gọi onGetNumber() lại sinh ra 1 instance mới của randomNumber thì hàm việc observer ở onCreate() sẽ không còn ý nghĩa nữa.
  • Kết luận: Không khai bào LiveData bằng biến var. Sử dụng Transformation operation ở bước khởi tạo.
  1. Giải pháp: Sử dụng Transformatio ở bước khởi tạo

III, Kết luận

  • Những sai lầm trên chúng ta rất có thể mắc phải mà không để ý.
  • Hi vọng bài viết giúp được mọi người trong việc sử dụng LiveData, ViewModel cùng với mô hình MVVM.

Happy coding


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí