BLoC

Business Logic Component — State Management pattern สำหรับ Flutter เปิดตัวโดย Google ที่ DartConf 2018 ใช้แนวคิด Event → BLoC → State ผ่าน Stream

ปัญหาที่แก้

เหมือน Riverpod คือแก้ปัญหา prop drilling — ส่ง state ผ่าน constructor หลายชั้น แต่ BLoC บังคับโครงสร้างชัดเจนกว่า เหมาะกับทีมใหญ่

แนวคิดหลัก

UI ส่ง Event  →  BLoC ประมวลผล  →  ปล่อย State ใหม่  →  UI rebuild
    (ปุ่มกด)       (business logic)     (ผ่าน Stream)

ทุกอย่างเป็น one-way data flow:

  • UI ไม่แก้ state ตรง → ส่ง Event เข้า BLoC เท่านั้น
  • BLoC รับ Event → ตัดสินใจ → ปล่อย State ใหม่ออกมา
  • UI รับ State ใหม่ → rebuild

Setup

# pubspec.yaml
dependencies:
  flutter_bloc: ^8.0.0

ส่วนประกอบ 3 ตัว

1. Event — สิ่งที่เกิดขึ้น

// events
abstract class CounterEvent {}
class IncrementPressed extends CounterEvent {}
class DecrementPressed extends CounterEvent {}

2. State — สถานะปัจจุบัน

// state (ใช้ class หรือค่าธรรมดาก็ได้)
class CounterState {
  final int count;
  const CounterState(this.count);
}

3. Bloc — ตัวประมวลผล

class CounterBloc extends Bloc<CounterEvent, CounterState> {
  CounterBloc() : super(const CounterState(0)) {
    on<IncrementPressed>((event, emit) {
      emit(CounterState(state.count + 1));
    });
    on<DecrementPressed>((event, emit) {
      emit(CounterState(state.count - 1));
    });
  }
}

ใช้ใน Widget

// ห่อ app ด้วย BlocProvider
BlocProvider(
  create: (context) => CounterBloc(),
  child: const MyApp(),
)
 
// อ่าน state
BlocBuilder<CounterBloc, CounterState>(
  builder: (context, state) {
    return Text('Count: ${state.count}');
  },
)
 
// ส่ง event
context.read<CounterBloc>().add(IncrementPressed());

Cubit — BLoC แบบย่อ

ถ้าไม่ต้องการ Event class แยก ใช้ Cubit ได้ — เรียก method ตรงๆ เหมือน function call:

class CounterCubit extends Cubit<int> {
  CounterCubit() : super(0);
 
  void increment() => emit(state + 1);
  void decrement() => emit(state - 1);
}
 
// ใช้: context.read<CounterCubit>().increment();
BlocCubit
inputEvent classmethod call ตรงๆ
boilerplateเยอะกว่าน้อยกว่า
traceabilityดีกว่า (เห็น event ทุกตัว)ดูยากกว่า
เหมาะกับlogic ซับซ้อน, ต้อง track eventslogic ง่าย, อยากเขียนไว

เปรียบเทียบกับ Riverpod

ด้านBLoCRiverpod
เปิดตัว2018 (DartConf)2020
แนวคิดEvent → Bloc → State (Stream)Provider + Notifier
Boilerplateเยอะ (Event, State, Bloc class)น้อย
โครงสร้างบังคับ pattern ชัดเจนยืดหยุ่นกว่า
เหมาะกับแอปใหญ่ ทีมใหญ่ enterpriseแอปทุกขนาด
Testingดีมาก (test event → state)ดี
ใน productionแพร่หลายมากเพิ่มขึ้นเรื่อยๆ

Key Points

  • BLoC บังคับ one-way data flow: UI → Event → Bloc → State → UI
  • ต้องสร้าง 3 ส่วน: Event, State, Bloc class — boilerplate เยอะแต่โครงสร้างชัด
  • Cubit คือ BLoC แบบย่อ ไม่ต้องสร้าง Event class
  • เก่าแก่และแพร่หลายในงาน enterprise — Google แนะนำตั้งแต่ 2018
  • Package หลัก: flutter_bloc โดย Felix Angelov
  • Riverpod — state management ทางเลือกที่ modern กว่า boilerplate น้อยกว่า
  • State Management — concept ภาพรวมการจัดการ state
  • Flutter — framework ที่ใช้ BLoC
  • Lifting State Up — วิธี share state แบบง่ายก่อนจะใช้ package