큐빗을 사용해야할 떄와 블록을 사용해야할 때 비교해보기
cubit을 사용하는 가장 큰 장점은 simple! / 큐빗을 만들 때 상태를 변경하기 위해 노출하려는 함수와 상태를 정의하기만 하면 되옵니다. 블록 생성시 상태, 이벤트 및 이벤트핸들러 구현 정의
큐빗을 더 쉽게 이해할 수 있고 관련된 코드가 더 적음
CounterCubit vs CounterBloc
class CounterCubit extends Cubit<int> {
CounterCubit() : super(0);
void increment() => emit(state + 1);
}
abstract class CounterEvent {}
class CounterIncrementPressed extends CounterEvent {}
class CounterBloc extends Bloc<CounterEvent, int> {
CounterBloc() : super(0) {
on<CounterIncrementPressed>((event, emit) => emit(state + 1));
}
큐빗 구현은 더 간결하고 이벤트를 별도로 정의하는 대신, 함수가 이벤트처럼 작동! 큐빗을 사용할 때 상태 변화를 트리거하기 위해 어디에서나 emit 호출 가능!
큐빗과 다르게 bloc은 추적성이 좋음
상태 변화와 순서와 이러한 변화를 촉발한 원인을 정확히 알고 있다는 것임! / 어플리케이션의 기능에 중요한 상태의 경우, 상태 변경뿐만 아니라 모든 이벤트를 포착하기 위해, 이벤트 중심적인 접근 방식을 사용하는 것이 매우 유용
enum AuthenticationState { unknown, authenticated, unauthenticated }
인증됨에서 인증되지 않음으로 변경될 때 / 사용자가 로그아웃 버튼을 눌러 응용 프로그램에서 로그아웃 하도록 요청 했을 수도 있음 / 반면 사용자의 액세스 토큰이 해지되어 강제 로그아웃이 가능 => bloc 사용 시 어플리케이션 상태가 어떻게 특정 상태가 되었는지 추적 가능!
Transition {
currentState: AuthenticationState.authenticated,
event: LogoutRequested,
nextState: AuthenticationState.unauthenticated
}
Change {
currentState: AuthenticationState.authenticated,
nextState: AuthenticationState.unauthenticated
}
// 위의 전환은 상태가 왜 변했는 지 이해하는데 필요한 모든 정보 제공 / 큐빗을 사용하면 어떻게 변하는지 디버깅하고 이해하는 데 중요한 이유 설명되지 않음!
진보된 이벤트 변환
bloc이 cubit보다 좋을 떄는 buffer, debounceTime, throttle 등과 같은 반응형 연산자를 활용해야할 때 유용함
블록에는 들어온느 이벤트의 흐름을 제어 / 변환할 수 있는 이벤트 싱크 있음
블록을 사용하면 들어오는 이벤트가 블록에 의해 처리되는 방식을 변경할 수 있는 사용자 정의 이벤트 변환기를 제공
EventTransformer<T> debounce<T>(Duration duration) {
return (events, mapper) => events.debounceTime(duration).flatMap(mapper);
}
CounterBloc() : super(0) {
on<Increment>(
(event, emit) => emit(state + 1),
/// Apply the custom `EventTransformer` to the `EventHandler`.
transformer: debounce(const Duration(milliseconds: 300)),
);
}
어떤 것을 사용해야 할지 여전히 잘 모르겠으면 큐빗부터 시작하여 나중에 필요에 따라 블록으로 리팩터링하거나 스케일업 할 수 있음!