DEV Community

Cover image for Simple overview on using cubits for state management
Ramiro - Ramgen
Ramiro - Ramgen

Posted on • Edited on

Simple overview on using cubits for state management

Alright so I'm making a revamp of my AiStickerMaker app and I have a functionality where you select an image from the gallery or the camera and a SliverAppBar widget will update with that image.

For this i was using a singleton to manage the state and passing that around, but as you can guess it wasn't a great option, it turns out changing the data in the singleton wasn't updating the state of the child widget.

So I decided to give blocs/cubits a shot, a decided this instead of provider because I thought that in the long run will be a better option.

Let's first see the implementation of the cubit I used, for what I gathered a cubit is a simple form of a bloc as it extends BlocBase, but it only holds one type of data, this can be a complex class with multiple fields or just a String.

class ImageSelectedCubit extends Cubit<String?> {
  // 1
  ImageSelectedCubit() : super('');
  // 2
  void getNewImage(ImageSource fileSource) async {
    final ImagePicker picker = ImagePicker();
    final XFile? pickedFile = await picker.pickImage(source: fileSource);
    emit(pickedFile?.path);
  }
  // 3
  void resetImage() {
    emit('');
  }
  // 4
  @override
  void onChange(Change<String?> change) {
    super.onChange(change);
    debugPrint(change.currentState);
    debugPrint(change.nextState);
  }
}
Enter fullscreen mode Exit fullscreen mode

First we create the cubit class extending cubit and declaring that it holds a String?

  1. We call the super of the class; with this we set the initial state
  2. This one is the function that updates the state with the selected image, here we call the pickImage function and with the result we call emit to update the value of the cubit
  3. A function to reset the state
  4. Then with this we can debug the change of state.

Alright awesome right? we have a cubit now what?
Well we need to provide this bloc in the right places, and use a consumer to listen to the bloc.

MaterialApp( //...
home: MultiBlocProvider(providers: [
        BlocProvider(
          create: (context) => ImageSelectedCubit(),
        ),
      ], child: const HomePage()),
);
Enter fullscreen mode Exit fullscreen mode

Now the best way I saw how to do this is to wrap the home in the MateralApp widget with a MultiBlocProvider, then we can state all of our providers inside of this widget and use them inside any children that follows this context.

Let's see how to actually use it and update a widget
For this we need to use the BlocConsumer widget, as said before a cubit is just a simpler Bloc so we can use any Bloc widget with it.

BlocConsumer<ImageSelectedCubit, String?>(
  listener: (context, state) {
    final imgCubit = context.read<ImageSelectedCubit>();
    if (state == null) {
      showSnack('Error!', context);
      imgCubit.resetImage();
    }
  },
  builder: (context, state) {
    final imgCubit = context.read<ImageSelectedCubit>();
    return Image(image: FileImage(File(imgCubit.state!)));
})
Enter fullscreen mode Exit fullscreen mode

Here we create a BlocConsumer with the type of the cubit that we want and the type of data it holds here <ImageSelectedCubit, String?>
Then this is optional but we can do data validation before we build the widget, here we check if the image selected is null and we reset the value to an empty string.

Now in the builder function we can access the instance of the cubit using context.read<T>() ( T is the class of your cubit ) then reading .state we access the value of the cubit.

And that's it, I really liked the simplicity of cubits, but I'm sure I'll be diving deeper into Blocs for the rest of the app, if you want to follow the development check out de YT vid! 😁

Top comments (4)

Collapse
 
nombrekeff profile image
Keff

I've no experience with cubits, but it feels to me like there is a lot of boilerplate for just storing the state of a string. Are cubits supposed to be small units of state or can they also hold more complex states?

I've been using provider on most apps we do at work, but I'm always interested in other solutions, but they always feel to bloated with boilerplate and stuff that makes me think again.

What benefits would you say cubits/bloc have over plain Providers?

Interesting post nonetheless, I will keep an eye for further updates on the subject!

Collapse
 
andreisas06 profile image
Andrei Sas

You are right, but Cubit is the simplified version of Bloc. Imagine the Bloc boilerplate. Of course there are specific usecases for these state management solutions, for instance I would use Bloc/Cubit for larger and more complex projects, and I would use Riverpod for most projects. That is my take.

Collapse
 
ramgendeploy profile image
Ramiro - Ramgen

That's interesting! i didn't have riverpod on my radar, i think it wasn't released at the moment i was doing the project xD
Maybe in the next one i'll try it out.

Collapse
 
ramgendeploy profile image
Ramiro - Ramgen

Yea the boiler plate is something i also didn't quite like, but perhaps I'm using a sledge hammer to drive a nail here xD

I'm very new to the bloc library but for what i understood cubits are similar to Providers, i guess i choose bloc because it may be a little more versatile in the future.

That's one of the areas that i want to explore, but i think bloc's might be more robust, and be more suitable for more complex state systems.

I think for a first look and having used other state management in other frameworks cubits seem pretty alright, we'll as I continue using it, definitely gonna do a more in depth blog with Blocs.