How can I use multiple cubits and emit states from both in the same screen?

Viewed 102

I need to rebuild the body of the home screen when I add new task to get all the tasks including the last task added, I tried many solutions from many resources but I didn't find an solution.

here the home screen widget which build list view of all tasks. Home screen widget

class HomeScreen extends StatelessWidget {    
  @override
  Widget build(BuildContext context) {
    return BlocConsumer<TasksCubit, TasksStates>(
      listener: (context, state) {},
      builder: (context, state) {
        TasksCubit cubit = TasksCubit.get(context);
        return Scaffold(
          body: ListView.separated(
            itemBuilder: (context, index) {
              return BuildTaskItem(
                task: cubit.tasksList[index],
              );
            },
            separatorBuilder: (context, index) => Divider(
              thickness: 1,
            ),
            itemCount: cubit.tasksList.length,
          ),
        );
      },
    );
  }
}

that the add screen which I can add task using insert into database(), when I add task and hit the button which trigger the function, it emits the add task success state and emits get tasks success but it isn't refresh the home screen with the new task

add task widget

Widget build(BuildContext context) {
    return BlocConsumer<TasksOperationsCubit, TasksOperationsStates>(
      listener: (context, state) {},
      builder: (context, state) {
        TasksOperationsCubit cubit = TasksOperationsCubit.get(context);
        return Scaffold( 
          body: Padding(
            padding: const EdgeInsets.all(20.0),
            child: SingleChildScrollView(
              child: Form(
                key: formKey,
                child: Column(
                  children: [
                    defaultMaterialButton(
                      color: Colors.pink,
                      text: 'Add Task',
                      textTheme: ButtonTextTheme.primary,
                      height: 50.0,
                      textSize: 25.0,
                      minWidth: double.infinity,
                      pressed: () {
                        if (formKey.currentState!.validate()) {
                          TaskEntity task = TaskEntity(
                            task: titleController.text,
                            date: dateController.text,
                            time: timeController.text,
                            piriority: piriorityController.text,
                            category: category,
                          );
                          cubit.insertIntoDatabase(task);
                        }
                      },

here the method that I add task into the database from the tasks operations cubit

tasks operations cubit

class TasksOperationsCubit extends Cubit<TasksOperationsStates> {
  TasksCubit tasksCubit;

  static TasksOperationsCubit get(context) => BlocProvider.of(context);

  void insertIntoDatabase(TaskEntity task) {
    insertTaskUsecase.todoRepository.insertTaskIntoDatabase(task).then((value) {
      value.fold((failure) {
        emit(InsertIntoDatabaseErrorState(error: failure.toString()));
      }, (unit) {
        emit(InsertIntoDatabaseSuccessState());
        tasksCubit.getAllTasks();
      });
    });
  }
}

here the get all tasks method form the the tasks cubit

tasks cubit

class TasksCubit extends Cubit<TasksStates> {

  static TasksCubit get(context) => BlocProvider.of(context);

  List<TaskEntity> tasksList = [];
  List<TaskEntity> getAllTasks() {
    LoadingGetAllTasksState();
    getAllTasksUsecase.todoRepository.getAllTasksFromDatabase().then((value) {
      value.fold((failure) {
        emit(GetAllTasksErrorState(error: failure.toString()));
      }, (tasks) {
        tasksList = List.from(tasks);
        print(tasks.toString());
        emit(GetAllTasksSuccessState());
      });
    });
    return tasksList;
  }
}

I wish someone can help me finding a solution, and thanks all.

2 Answers

emit a cubit event from task adding widget after task is added, listen to that state and build home screen using that, make sure state is changing, if state is not changing create a dummy state and switch between state.

use listenWhen and buildWhen of bloc consumer in home widget for more convenience.

I am tried so many times until finally I found the answer all what I had to do just nest the bloc builder method at the home screen and create the proper implementations.

and here what I did

  class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: _buildAppbar(context),
      body: BlocConsumer<TasksCubit, TasksStates>(
        listener: (context, state) {},
        builder: (context, state) {
          return BlocConsumer<TasksOperationsCubit, TasksOperationsStates>(
            listener: (operationsContext, operationsState) {
              if (operationsState is InsertIntoDatabaseSuccessState ||
                  operationsState is DeleteTaskItemSuccessState ||
                  operationsState is UpdateTaskItemSuccessState) {
                TasksCubit.get(context).getAllTasks();
              }
            },
            builder: (operationsContext, operationsState) {
                return _buildTasks(state.tasks);
            },
          );
        },
      ),
    );
  }
Related