How to use StreamSubscription with Flutter Cubit

Viewed 2712

I am with a problem that the stream subscription to a cubit doesn't listen to the emitting state of the cubit. Here's an example of how I implemented them in my code.

This is the cubit which I want to listen

class ButtonPressCubit extends Cubit<ButtonState> {

  ButtonPressCubit() : super(ButtonNotPressed());

  void emitButtonOnePressed() => emit(ButtonOnePressed());
  void emitButtonTwoPressed() => emit(ButtonTwoPressed());

}
part of 'internet_cubit.dart';

@immutable
abstract class ButtonState {}

class ButtonNotPressed extends ButtonState {}

class ButtonOnePressed extends ButtonState {}

class ButtonTwoPressed extends ButtonState {}

This is the cubit that I want to subscribe to the cubit that I want to listen to.

class CounterCubit extends Cubit<CounterState> {
  final ButtonPressCubit buttonPressCubit;
  StreamSubscription buttonPressStreamSubscription;
  CounterCubit({@required this.internetCubit})
      : super(CounterState(counterValue: 0, wasIncremented: false)) {
    buttonPressStreamSubscription = buttonPressCubit.listen(print);
  }

  void increment() => emit(
      CounterState(counterValue: state.counterValue + 1, wasIncremented: true));

  void decrement() => emit(CounterState(
      counterValue: state.counterValue - 1, wasIncremented: false));

  @override
  Future<void> close() {
    buttonPressStreamSubscription.cancel();
    return super.close();
  }
}

After that, I called the ButtonPressCubit emitButtonOnePressed() like below.

MaterialButton(
  child: Text('Buton 2'),
  onPressed: () {
    BlocProvider.of<ButtonPressCubit>(context)
      .emitButtonTwoPressed();
    },
),

But this doesn't work. how to fix it to get the state of the cubit.

1 Answers

If you didn't register the Cubit of that widget before you start it, you should do it

it's like telling the flutter that this Cubit is for this page and there are some approaches for that

first: if you have more than one Bloc or

 MultiBlocProvider(
      providers: [
        //other Blocs or Cubits
        BlocProvider<XCubit>(
          create: (BuildContext context) => XCubit(),
          child: XWidget(),
        ),
        //other Blocs or Cubits
      ],
      child: MaterialApp(),....);

Second: as in Documentation

class _AppState extends State<App> {
  final UserRepository _userRepository = UserRepository();
  AuthenticationBloc _authenticationBloc;

  @override
  void initState() {
    super.initState();
    _authenticationBloc = AuthenticationBloc(userRepository: _userRepository);
    _authenticationBloc.dispatch(AppStarted());
  }

  @override
  Widget build(BuildContext context) {
    return BlocProvider(
      bloc: _authenticationBloc,
      child: MaterialApp(
        home: BlocBuilder(
          bloc: _authenticationBloc,
          builder: (BuildContext context, AuthenticationState state) {
            //here is your widget you want to run
            return Container();
          },
        ),
      ),
    );
  }

but remember you should do it before start/run your widget

Usually I define all the Blocs and Cubits in the beginning like the first method.. in the beginning before any other widget run.

that's thing the other thing you should care about is but this one if you are using Bloc not Cubit is you implement the Bloc

{Listener,Builder..}in your widget so you can see the changes

  BlocBuilder<AddNewStudentBloc, AddNewStudentState>(
          builder: (context, state) {
//here you do respond for the state like 
// if State is Error return ErrorWidget
// else if the state is Success return SuccessWidget
// and so on....
return Container(); },
    );
Related