Flutter/Bloc

Bloc (3) - Cubit과 Bloc 코드로 이해하기

smileDeveloper 2024. 1. 31. 00:10
반응형
SMALL

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은 이벤트와 상황을 미리 정의해놓기에 추적이 가능한다는 점과 향상된 이벤트 흐름을 제어할 수 있다는 점이 좋다

 

 

 

다음 포스팅에선 실제 예제를 보며 이해하는 시간을 가져보겠습니다. 감사합니다

반응형
LIST

'Flutter > Bloc' 카테고리의 다른 글

Bloc (2) - Cubit과 Bloc의 개념  (0) 2024.01.23
Bloc (1) - Bloc 이란  (0) 2024.01.21
Bloc (0) - Bloc 배워보기  (1) 2024.01.09