Bloc Pattern cơ bản trong Flutter

1. Bloc Pattern là gì

Bloc Pattern là một Pattern :D, mục đích chính của Pattern này là tách code business logic ra khỏi UI thay vì gộp chung logic và UI vào cùng 1 file. Code business logic được tách ra đó được đặt tên là Bloc (Business Logic Component). Bên cạnh đó, nó giúp quản lý state của 1 màn hình tốt hơn vì các state sẽ được quản lý ở Bloc tách biệt với UI. Chính vì thế, mỗi màn hình trong flutter sẽ tạo ra 1 bloc để xử lý logic và quản lý logic của màn hình đó.

Bloc định nghĩa ra các state, các event. Bloc nhận event từ UI, xử lý logic, biến chuyển state và bắn về UI để cập nhật giao diện. Tư tưởng của bloc khá giống với ReactorKit trong Swift.

Trong Bloc, để nhận event input và phát ra state output, chúng ta cần sử dụng tới Stream Controller để triển khai. Input sẽ được thêm vào sink của StreamController và phía UI sẽ sử dụng stream để lắng nghe nhận state mỗi khi có event được add vào sink

2. Ví dụ minh họa

Để hiểu hơn về bloc, chúng ta sẽ làm 1 màn hình đơn giản như sau:

Màn hình bao gồm 1 Text hiển thị số, 2 Button +1 và -1 để tăng hoặc giảm số trên màn hình 1 đơn vị.

Như vậy, có thể dễ dàng nhận thấy có 2 event là tăng và giảm, state chính là giá trị được hiển thị lên màn hình. Tiến hành code thôi nào.

Bước 1: Định nghĩa các event

abstract class CounterEvent {}

class IncrementEvent extends CounterEvent {
  IncrementEvent(this.value);
  final int value;
}

class DecrementEvent extends CounterEvent {
  DecrementEvent(this.value);
  final int value;
}

Như đã phân tích ở trên, event bao gồm tăng và giảm. Chúng ta sẽ tạo ra 2 lớp event là IncrementEvent và DecrementEvent. 2 lớp này đều có giá trị đầu vào là value với ý nghĩa là tăng hoặc giảm bao nhiêu đơn vị. Trong bài toán cụ thể này, value sẽ bằng 1.

Bước 2: Định nghĩa state

class CounterState {
  CounterState({required this.count});
  int count;

  CounterState copyWith({int? count}) {
    return CounterState(count: count ?? this.count);
  }
}

Tạo lớp CounterState để quản lý các state của màn hình. Trong đó, count là state để hiển thị bộ đếm lên màn hình.

Bước 3: Code logic trong Bloc

Tạo 1 file counter_bloc.dart để chứa logic. Như đã giới thiệu ở trên, nhiệm vụ của bloc là nhận event từ UI, xử lý event và cập nhật lại state. UI lắng nghe state để cập nhật giao diện.

class CounterBloc {
  // Khởi tạo state, init giá trị khởi tạo
  var state = CounterState(count: 0);
  
  // Khởi tạo event controller để nhận event từ UI
  final eventController = StreamController<CounterEvent>.broadcast();
  // Khởi tạo state controller để truyền state đến UI
  final stateController = StreamController<CounterState>.broadcast();

  CounterBloc() {
    eventController.stream.listen((event) {
      if (event is IncrementEvent) {
        state = state.copyWith(count: state.count + event.value);
      } else if (event is DecrementEvent) {
        state = state.copyWith(count: state.count - event.value);
      }
      stateController.sink.add(state);
    });
  }

  void dispose() {
    stateController.close();
    eventController.close();
  }
}

Bước 4: Tích hợp bloc vào UI

import 'package:bloc_example/screen/counter/counter_bloc.dart';
import 'package:flutter/material.dart';

class CounterScreen extends StatelessWidget {
  // Khởi tạo bloc
  var bloc = CounterBloc();
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text("Counter"),
        ),
        body: Center(
          // Sử dụng StreamBuilder để lắng nghe thay đổi stream của stateController và update lại UI
          child: StreamBuilder(
              stream: bloc.stateController.stream,
              initialData: bloc.state, // Khởi tạo giá trị mặc định
              builder:
                  (BuildContext context, AsyncSnapshot<CounterState> snapshot) {
                return Text(
                  (snapshot.data?.count ?? 0).toString(),
                  style: const TextStyle(
                    fontSize: 70,
                    fontWeight: FontWeight.bold,
                  ),
                );
              }),
        ),
        floatingActionButton: Column(
          mainAxisAlignment: MainAxisAlignment.end,
          children: [
            IconButton(
              onPressed: () {
                // truyền action vào bloc
                bloc.eventController.sink.add(IncrementEvent(1));
              },
              icon: const Icon(
                Icons.plus_one,
                size: 30,
                color: Colors.white,
              ),
              style: const ButtonStyle(
                  backgroundColor: WidgetStatePropertyAll(Colors.blue)),
            ),
            IconButton(
              onPressed: () {
                // truyền action vào bloc
                bloc.eventController.sink.add(DecrementEvent(1));
              },
              icon: const Icon(
                Icons.exposure_minus_1,
                size: 30,
                color: Colors.white,
              ),
              style: const ButtonStyle(
                  backgroundColor: WidgetStatePropertyAll(Colors.blue)),
            ),
          ],
        ));
  }
}

Kết luận

Như vậy, mình đã giới thiệu cơ bản về Bloc Pattern. Để nâng cao hơn về bloc và tăng tốc độ code, các bạn có thể dùng thêm thư viện như flutter_bloc

Nguồn tham khảo:

https://viblo.asia/p/hoc-bloc-pattern-theo-cach-de-hieu-nhat-maGK7JYO5j2

Tôi là một lập trình viên IOS. Code chính là IOS nhưng thỉnnh thoảng vẫn đá sang Android hoặc web. Mặc dù không quá thông thạo nhưng tôi sẽ chia sẻ những kiến thức mà mình đã tìm hiểu, áp dụng qua.

Bài viết liên quan

Doanh nghiệp của bạn không phù hợp với điện thoại – Ứng dụng Flutter của bạn cũng vậy

Một quán cà phê hiện đại chạy trên nhiều màn hình.

Xem thêm

Doanh nghiệp của bạn không phù hợp với điện thoại – Ứng dụng Flutter của bạn cũng vậy

Một quán cà phê hiện đại chạy trên nhiều màn hình.

Xem thêm

Xây dựng trên Nostr: Những thách thức kỹ thuật thực sự

Đây là Phần 2 của loạt bài gồm hai phần.

Xem thêm
0 0 đánh giá
Article Rating
Theo dõi
Thông báo của
guest
11 Comments
Cũ nhất
Mới nhất Được bỏ phiếu nhiều nhất
Phản hồi nội tuyến
Xem tất cả bình luận
trackback
1 tháng trước

[…] viagra connect […]

trackback
1 tháng trước

[…] farmacia online miglior prezzo […]

trackback
1 tháng trước

[…] apothekennotdienst in der nähe […]

trackback

[…] online casino games real money […]

trackback
21 ngày trước

[…] sildenafil 50 mg price at walmart […]

trackback
18 ngày trước

[…] figral sildenafil 100mg […]

trackback
18 ngày trước

[…] generic viagra 50 mg […]

trackback
18 ngày trước

[…] cialis professional […]

trackback
18 ngày trước

[…] buy cialis 40mg […]

trackback

[…] how much is cialis […]

trackback
18 ngày trước

[…] viagra 25mg cost […]