Search code examples
flutterdartbloc

How Can I Escape Multiple Listed Widget (Button) State Management with Flutter Bloc?


I am managing states using Flutter Bloc. I have a list. When you press the + button, it is added to the list by sending a request to the API. Circular Progress Indicator is displayed in case of installation and successful icon in case of completion.

However, the situation changes for all buttons, not the relevant button. How do I change the state of only the button pressed?

More Than One Button State

return ListView.builder(
    itemCount: state.model.length,
    itemBuilder: (context, index) {
      return ListTile(
          title: Text(
            state.model[index].title ?? "",
            style: TextStyle(fontWeight: FontWeight.w500),
          ),
          subtitle: Text("${state.model[index].subTitle}"),
          trailing: BlocConsumer<CarCubit, CarState>(
              listener: (context, state) {
            if (eatState is CarError) {
              final snackBar = SnackBar(
                content: Text(state.message ?? ""),
              );
              ScaffoldMessenger.of(context).showSnackBar(snackBar);
            }
          }, builder: (context, state) {
            return TextButton(
                onPressed: state is CarInitial
                    ? () {
                        context.read<CarCubit>().addList(
                            CarModel(
                              title: state.model[index].title,
                              category: state.model[index].category,
                              image: state.model[index].image,
                            ));
                      }
                    : null,
                child: carStateWidget(state));
          }));
    });

Widget carStateWidget(CarState state) {
    if (state is CarLoading) {
      return CircularProgressIndicator(
        color: Colors.white,
      );
    } else if (state is CarCompleted) {
      return Icon(
        Icons.done,
        color: Colors.white,
      );
    }
    return Text("+", style: TextStyle(color: Colors.white));
  }

Solution

  • You can create carId instance to the CarLoading state class and when emitting it just check if the current carId of the loading button of this car object (I have supposed that each car is an object and has a carId instance) matches the received id from the state.

    Something like that:

    Widget carStateWidget(CarState state, int carId) {  // carId
        if (state is CarLoading && state.carId == carId) {  // check
          return CircularProgressIndicator(
            color: Colors.white,
          );
        } else if (state is CarCompleted) {
          return Icon(
            Icons.done,
            color: Colors.white,
          );
        }
        return Text("+", style: TextStyle(color: Colors.white));
      }
    

    Note, don't use methods to create widgets as this is not recommended even officially by flutter team for many reasons, you can check this.