Simple overview on using cubits for state management
Tags: flutter, android, beginners
Published: 2022-07-31 22:26:00

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`.

```dart
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);
  }
}
```
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.

```dart
MaterialApp( //...
home: MultiBlocProvider(providers: [
        BlocProvider(
          create: (context) => ImageSelectedCubit(),
        ),
      ], child: const HomePage()),
);
```
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.

```dart
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!)));
})
```
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! 😁

{% embed https://www.youtube.com/watch?v=VBJVd3xhHsI %}