flutterdartblocflutter-blocfreezed

Freezed+BLoc how to check the current state and the variables of an specific state from BLoc Listener


I'm trying to learn how to execute some code in a BLoC listener depending on the state and a code variable that's only present in the success state.
I would like to be able to tell if I'm on the Success state from the Listener, and also, access It's current code

Those are my bloc states:

@freezed
class ExampleState with _$ExampleState {
  const factory ExampleState.initial() = _Initial;
  const factory ExampleState.success(int code) = _Success;
  const factory ExampleState.error() = _Error;
}

And the bloc

class ExampleBloc extends Bloc<ExampleEvent, ExampleState> {
  ExampleBloc() : super(_Initial()) {
    on<_ChangeCode>((event, emit) {
      if(state is _Success){
        int stateCode = (state as _Success).code;
        debugPrint("Ey, I got the current code:  $stateCode");
        //Would like to access this code variable in a similar way in the listener
      }
      emit(ExampleState.success(event.newCode));
    });
  }
}

And finally, this is the Listener that listens to ExampleBloc:

listener: (context, state) {
               //Would like to check if the state is success

               //Would like to print something if the state.code == 5
              },

The solutions I've found are the following:

Add the code variable to all states, so I can do "state.code"

@freezed
class ExampleState with _$ExampleState {
  const factory ExampleState.initial(int code) = _Initial;
  const factory ExampleState.success(int code) = _Success;
  const factory ExampleState.error(int code) = _Error;
}

And then I could do:

 listener: (context, state) {
    debugPrint(state.code.toString());
 },

I don't really like this solution as it is really annoying to use on the long run.
-
The other option, would be removing the underscore of the state that I want to check, like so:

@freezed
class ExampleState with _$ExampleState {
  const factory ExampleState.initial() = _Initial;
  const factory ExampleState.success(int code) = Success;
  const factory ExampleState.error() = _Error;
}

and then I Could do:

 listener: (context, state) {
   if(state is Success){
     debugPrint(state.code.toString());
   }
 },

But I don't know if the seccond approach is a bad practice, as the state It's private by default, so maybe I shouldn't remove the underscore.


Solution

  • Your freezed class is a "union type", and there are methods called maybeWhen and when that you can use to handle the different states, so you can simply do this:

    listener: (context, state) {
       state.when(
         initial: () {...},
         success: (int code) {...},
         error: () {...}
       );
    },