Cubit
class Cubit extends BlocBase
class CounterCubit extends Cubit<int> {
CounterCubit(int initialState) : super(initialState);
}
- Cubit은 BlocBase를 상속합니다.
- Cubit<T> 내부의 클래스로 관리할 상태 유형을 지정합니다.
- 위와 같이 코드를 작성할 경우 다양한 초기 상태로 인스턴스화 할 수 있습니다.
class CounterCubit extends Cubit<int> {
CounterCubit() : super(0);
void increment() => emit(state + 1);
}
- state는 처음에 지정한 상태 유형의 값입니다.
- emit을 통해 상태를 변환합니다.
- emit은 Cubit 내부에서만 작성되어야 합니다.
Future<void> main() async {
final cubit = CounterCubit();
print(cubit.state); // 0
cubit.increment();
print(cubit.state); // 1
final subscription = cubit.stream.listen(print); // 2
cubit.increment();
await Future.delayed(Duration.zero);
await subscription.cancel();
await cubit.close();
}
- 생성된 cubit은 state와 stream으로 값을 확인 할 수 있습니다.
- stream은 구독을 끊기 전까지 계속해서 cubit의 상태 값이 바뀔 때마다 수신합니다.
class CounterCubit extends Cubit<int> {
CounterCubit() : super(0);
void increment() => emit(state + 1);
@override
void onChange(Change<int> change) {
super.onChange(change);
print(change);
}
}
- cubit 내부에서 상태 값의 변화를 감지할 수 있습니다.
- 변화할 때의 출력하는 예시는 다음과 같습니다. "Change { currentState: 0, nextState: 1 }"
Bloc
class Bloc extends BlocBase
sealed class CounterEvent {}
final class CounterIncrementPressed extends CounterEvent {}
class CounterBloc extends Bloc<CounterEvent, int> {
CounterBloc() : super(0) {
on<CounterIncrementPressed>((event, emit) {
// handle incoming `CounterIncrementPressed` event
});
}
}
- Bloc은 Cubit과 마찬가지로 BlocBase를 상속합니다.
- Bloc은 Cubit과 달리 이벤트를 추가로 정의해야 합니다. 상태와 이벤트를 같이 정의합니다.
- 호출자에 이벤트 핸들러를 정의해야 합니다.
- 이벤트에 의해 상태 값이 바뀌는 로직을 권장합니다.
- Cubit과 마찬가지로 중복 값은 이벤트가 발생하지 않습니다.
Future<void> main() async {
final bloc = CounterBloc();
print(bloc.state); // 0
final subscription = bloc.stream.listen(print); // 1
bloc.add(CounterIncrementPressed());
await Future.delayed(Duration.zero);
print(bloc.state); // 1
await subscription.cancel();
await bloc.close();
}
- bloc도 마찬가지로 상태 값의 변화를 감지할 수 있습니다.
@override
void onTransition(Transition<CounterEvent, int> transition) {
super.onTransition(transition);
print(transition);
}
- 이벤트의 변화를 감지합니다. 예시는 다음과 같습니다. "Transition { currentState: 0, event: Instance of 'CounterIncrementPressed', nextState: 1 }"
Observer
class SimpleBlocObserver extends BlocObserver {
@override
void onChange(BlocBase bloc, Change change) {
super.onChange(bloc, change);
print('${bloc.runtimeType} $change');
}
@override
void onTransition(Bloc bloc, Transition transition) {
super.onTransition(bloc, transition);
print('${bloc.runtimeType} $transition');
}
@override
void onError(BlocBase bloc, Object error, StackTrace stackTrace) {
print('${bloc.runtimeType} $error $stackTrace');
super.onError(bloc, error, stackTrace);
}
}
- 모든 Cubit과 Bloc의 변화를 감지합니다. main.dart에 Bloc.observer = SimpleBlocObserver()로 선언하면 모든 값의 변화를 로그로 출력합니다.
Error Handling
addError(Exception('increment error!'), StackTrace.current);
- Cubit과 Bloc 모두 위 메소드를 통해 에러를 처리합니다.
Cubit VS Bloc
- Cubit은 코드적인 측면에서 단순하다는 점이 좋다
- Bloc은 이벤트와 상황을 미리 정의해놓기에 추적이 가능한다는 점과 향상된 이벤트 흐름을 제어할 수 있다는 점이 좋다
다음 포스팅에선 실제 예제를 보며 이해하는 시간을 가져보겠습니다. 감사합니다
'Flutter > Bloc' 카테고리의 다른 글
Bloc (2) - Cubit과 Bloc의 개념 (0) | 2024.01.23 |
---|---|
Bloc (1) - Bloc 이란 (0) | 2024.01.21 |
Bloc (0) - Bloc 배워보기 (1) | 2024.01.09 |