Cubit은 BLoC 패턴을 간소화한 버전입니다. BLoC에서는 상태(State)와 이벤트(Event)를 각각 정의하고 관리해야 하지만, Cubit은 상태(State) 클래스만 구현하고, 메서드를 통해 이벤트를 처리합니다. 이를 통해 코드의 복잡성을 줄이고 더 간단하게 상태 관리를 할 수 있습니다.
BLoC(Business Logic Component) 패턴은 애플리케이션을 다음과 같은 구성 요소로 나누어 관리합니다:
View
: 사용자 인터페이스(UI)와 관련된 부분.State
: 현재 상태를 나타내는 객체.Event
: 상태를 변경하는 이벤트.Data
: 애플리케이션의 데이터.BLoC 패턴은 Stream
을 이용하여 상태와 이벤트를 송수신하며, 이를 통해 View
와 비즈니스 로직을 분리하여 구조적으로 관리합니다.
Cubit 클래스
: 상태를 관리하는 기본 클래스입니다. Cubit<상태 타입>
을 상속받아 커스텀 Cubit을 생성하고, 상태 변경 로직을 정의합니다.상태(States)
: Cubit의 상태는 단순한 Dart 객체입니다. 상태가 변경될 때마다 새로운 객체로 대체되어 UI가 업데이트됩니다.상태 전환(Emit)
: emit
메서드를 통해 새로운 상태로 전환합니다. 상태가 전환되면 이를 구독하고 있는 UI 컴포넌트들이 자동으로 업데이트됩니다.state
: 현재 상태를 나타냅니다.emit(newState)
: 새로운 상태로 전환합니다.Cubit
생성자: 초기 상태를 설정합니다.아래 예제는 Cubit을 사용하여 카운터를 증가시키고 감소시키는 방법을 보여줍니다.
import 'package:bloc/bloc.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
// Cubit 클래스 정의
class CounterCubit extends Cubit<int> {
CounterCubit() : super(0); // 초기 상태는 0
void increment() => emit(state + 1); // 상태 증가
void decrement() => emit(state - 1); // 상태 감소
}
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
Widget build(BuildContext context) {
return MaterialApp(
home: BlocProvider(
create: (_) => CounterCubit(),
child: CounterPage(),
),
);
}
}
class CounterPage extends StatelessWidget {
Widget build(BuildContext context) {
final counterCubit = context.read<CounterCubit>();
return Scaffold(
appBar: AppBar(title: Text('Cubit Counter Example')),
body: Center(
child: BlocBuilder<CounterCubit, int>(
builder: (context, count) {
return Text('$count', style: TextStyle(fontSize: 24));
},
),
),
floatingActionButton: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
FloatingActionButton(
child: Icon(Icons.add),
onPressed: () => counterCubit.increment(),
),
SizedBox(height: 8),
FloatingActionButton(
child: Icon(Icons.remove),
onPressed: () => counterCubit.decrement(),
),
],
),
);
}
}
context.watch()
: 상태가 변경될 때마다 위젯을 갱신합니다.context.read()
: 상태가 변경되어도 위젯을 갱신하지 않습니다.BlocBuilder
: 특정 위젯만 갱신합니다. buildWhen
을 사용하여 갱신 여부를 결정할 수 있습니다.BlocProvider
: 상태 변경 알림 기능이 있는 Cubit을 위젯 트리에 등록할 때 사용합니다.RepositoryProvider
: 상태 변경 알림 기능이 없는 클래스를 위젯 트리에 등록할 때 사용합니다.Cubit 간의 상태 변경을 동기화하려면 StreamSubscription
을 사용하여 다른 Cubit의 상태 변화를 수신하고, 이를 바탕으로 상태를 업데이트합니다. 이를 통해 여러 Cubit 간의 상호 작용을 구현할 수 있습니다.
StreamSubscription
을 사용한 경우, 반드시 구독을 해제해야 메모리 누수를 방지할 수 있습니다. 이를 위해 close
메서드를 호출하여 Cubit
이 더 이상 필요 없을 때 구독을 해제해야 합니다.
class ExampleCubit extends Cubit<ExampleState> {
final AnotherCubit anotherCubit;
late StreamSubscription anotherCubitSubscription;
ExampleCubit(this.anotherCubit) : super(InitialExampleState()) {
anotherCubitSubscription = anotherCubit.stream.listen((state) {
// Handle state changes
});
}
Future<void> close() {
anotherCubitSubscription.cancel();
return super.close();
}
}
하나의 Cubit 클래스에서 여러 상태를 관리하려면 상태 클래스를 불변 객체로 생성합니다. copyWith
메서드를 사용하여 불변 객체의 특정 속성만 변경하고, 새로운 객체를 생성하여 상태를 전환합니다.