Kiến trúc sư trong dự án Flutter sử dụng mẫu BLOC P2

Tram Ho

Trong bài viết hôm nay, mình sẽ giải quyết 1 số vấn đề mà kiến trúc của bài trước bao gồm :

  1. Giải quyết của các vấn đề hiện tại .
  2. Single Instance và Scoped Instance (BLoC access)
  3. Navagation.
  4. RxDart’s Transformers.

1. Giải quyết của các vấn đề hiện tại .

Trong bài trước lỗi đầu tiên là mình tạo method dispose() trong class MoviesBloc , hàm này có tác dụng close hoặc dispose tất cả các luồng stream để tránh rò rĩ bộ nhớ. nhưng nó không được gọi ở bất cứ đâu cả, điều này có thể gây rò rĩ bộ nhớ. Một lỗi khác là tôi đang thực hiện call network bên trong hàm build.

Class MovieList trong code hiện tại đang dùng StatelessWidget, hàm build sẽ được gọi bất cứ khi nào nó được thêm vào cây Widget . Do mình đặt hàm bloc.fetchAllMovies() (xem code phần 1) bên trong hàm build cho nên nó bị gọi nhiều lần . Vì sao mình nói như vậy vì class MovieList là class được kế thừa từ StatelessWidget, mà các bạn đã biết 1 class StatelessWidget sẽ call lại hàm build khi class đó phụ thuộc vào thằng class chứa nó, nếu thằng class cha Update UI thì thằng class MovieList sẽ thực hiện call lại hàm build.
Class MovieList nó không có các hàm initState and dispose như class StatefulWidget. Method initState chỉ gọi lần đâu khi cấp phát resource còn method dispose nó call disposing đã cấp phát resource . Bây giờ mình sẽ chuyển class MovieList kế thừa từ StatefulWidget .
Trong class movie_list.dart thay đoạn code sau :

Trong đoạn code trên tôi gọi bloc.fetchAllMovies() trong method initState còn bloc.dispose() trong method dispose của class MovieListState.

Note: Không bao giờ thực hiện call network or xử lý db ở trong hàm build và đảm bảo rằng bạn đã dispose hoặc close luồng stream.

2. Thực hiện tính năng mới

Mình sẽ thực hiện thêm tính năng detail movile khi người dùng click vào 1 bộ phim , các bạn xem video dưới đây :
https://www.youtube.com/embed/krXb9CzGRxU?feature=o

3. Lập Kế hoạch cho luồng app

Trước khi thêm 1 màn hình nào thì cách tốt nhất bạn viết trước ra giấy để hình dung được luồng của bạn đi như thế nào. Ví dụ :

Mình sẽ giải thích về flow của hình trên :

  1. Movie List Screen: sẽ hiển thị list các bộ phim theo dạng grid list.
  2. Movie List Bloc: đây là cầu nối để lấy dữ liệu từ repository và truyền nó đến màn Movie List Screen.
  3. Movie Detail Screen: đây là màn bạn sẽ xem thông tin chi tiết của bộ phim .
  4. Repository: đây là trung tâm từ đó luồng data được controller.
  5. API provider: Triển khai việc call api .

2. Single Instance và Scoped Instance

Trên màn hình Movie List Screen các bạn có thể lấy bloc theo 2 cách Single Instance , Scoped Instance. Single Instance có thể được truy cập ở bất cứ đâu trên app còn Scoped Instance có quyền truy cập hạn chế , nó chỉ được truy cập ở màn hình mà nó liên kết.

Nhìn trên diagram, Bloc chỉ có thể truy cập vào màn hình và 2 widget bên dưới màn hình. Chúng ta có thể dùng InheritedWidget để giữ Bloc trong nó . InheritedWidget sẽ wrap Screen widget, cho phép Screen và widget dưới nó có thể truy cập .
Single Instance là cách truy cập Bloc đối với app nhỏ nhưng làm việc với app lớn thì dùng Scoped Instance là cách tuyệt vời.

3. Adding the detail screen

Thêm màn hình detail cho app. Khi user click vào 1 bô phim sẽ hiển thị màn detail và show các thông tin về bồ phim. Tạo file movie_detail.dart , thêm đoạn code sau :

Bạn có thể hàm khởi tạo của class này cần thêm 1 vài tham số . Mình sẽ thêm logic để đưa màn hình danh sách sang màn hình detail .

1. Navigation

Trong Flutter nếu bạn muốn chuyển từ màn hình này sang màn hình khác bạn dùng Navigator . Hãy triển khai logic điều hướng bên trong file movie_list.dart .
Khi bạn tap 1 bộ phim thì sẽ mở ra màn hình detail screen và sẽ show data truyền từ màn list movie sang màn hình detail .

Bây giờ , tại màn movie detail hãy show đoạn intro lấy từ API :

Trong api trên chúng ta thay thế đoạn <movie_id> và your_api_key.
Response của api trả về là :

Đối với đoạn response trên chúng ta cần tạo class POJO. Tạo file trailer_model.dart trong package model.

Trong file movie_api_provider.dart hãy page đoạn code sau :

Update đoạn code sau vào file **repository.dart **:

Bây giờ hãy triển khai Scoped Instance BLoC .Tạo file movie_detail_bloc.dart trong blocs package, tạo file movie_detail_bloc_provider.dart cũng trong blocs package.
Đoạn code của file movie_detail_bloc_provider.dart :

Class có thể mở rộng từ class InheritedWidget và cung cấp truy cập bloc thông qua context. Context này được bọc trong InheritedWidget.
Viết thêm đoạn code movie_detail_bloc.dart :

Tôi sẽ giải thích cho bạn 1 chút : Để get được data trailer từ server chúng ta sẽ gửi movile id lên và lấy về list danh sách các đoạn trailer . Để thực hiện ý tưởng trên tôi sẽ dùng RxDart – Transformers. Tôi sẽ giới thiệu phần này ở bài học .

Tài liệu tham khảo :

https://medium.com/codechai/architect-your-flutter-project-using-bloc-pattern-part-2-d8dd1eca9ba5

Chia sẻ bài viết ngay

Nguồn bài viết : Viblo