Search code examples
flutterflutter-dependenciesflutter-bloc

Why page is build multiple times if I watch states?


I am working on the app where I have multiple cubit states and sometimes I only need to watch them to get data but I am not building a page. Now issue is that page is building multiple times in relation with number of states coming. If there 2 states, then it will be build 2 times and if there are three states, I am watching it will be build 3 times. Therefore, I retrieve same values multiple times. I do not know, why it is like this? Anybody can explain me and tell me what is the solution. Below is very simple script for your help.

class DocumentationsScreen extends StatelessWidget {
  const DocumentationsScreen({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    
    var agentState = context.watch<AgentsCubit>().state;
    var clientState = context.watch<ClientsCubit>().state;
    var groupState = context.watch<GroupsCubit>().state;
      
    //Widget is build multiple times according to number of states, I am watching.
   }
}

Solution

  • I think that the reason why your widget is being built multiple times is because you are calling context.watch on multiple cubit states in your build method. Whenever any of these cubit states change, the build method will be called again to rebuild the widget with the updated data. I see one solution is to create a fourth block that will subscribe to the changing states of the three blocks and respond as you need:

    
        class CombinedCubit extends Cubit<CombinedState> {
          final AgentsCubit agentsCubit;
          final ClientsCubit clientsCubit;
          final GroupsCubit groupsCubit;
    
          StreamSubscription agentsSubscription;
          StreamSubscription clientsSubscription;
          StreamSubscription groupsSubscription;
    
          CombinedCubit({
            required this.agentsCubit,
            required this.clientsCubit,
            required this.groupsCubit,
          }) : super(CombinedState(
                  agentsState: agentsCubit.state,
                  clientsState: clientsCubit.state,
                  groupsState: groupsCubit.state,
                )) {
            agentsSubscription = agentsCubit.stream.listen((state) {
              emit(state.copyWith(agentsState: state));
            });
            clientsSubscription = clientsCubit.stream.listen((state) {
              emit(state.copyWith(clientsState: state));
            });
            groupsSubscription = groupsCubit.stream.listen((state) {
              emit(state.copyWith(groupsState: state));
            });
          }
    
          @override
          Future<void> close() {
            agentsSubscription.cancel();
            clientsSubscription.cancel();
            groupsSubscription.cancel();
            return super.close();
          }
        }
    

    then you can use this combined cubit in BlocBuilder:

    class DocumentationsScreen extends StatelessWidget {
      final CombinedCubit combinedCubit;
    
      const DocumentationsScreen({Key? key, required this.combinedCubit})
          : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return BlocBuilder<CombinedCubit, CombinedState>(
          cubit: combinedCubit,
          builder: (context, state) {
            ...
          },
        );
      }
    }