Search code examples
flutterdartbloccubitflutter-cubit

Update a widget from another one with Cubit Bloc


I have two widgets on a screen a Loading Widget and a button widget I want to change the state of the loading widget every time I tap on the button.

loading widget

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

  @override
  Widget build(BuildContext context) {
    return BlocBuilder<LoadingCubit, bool>(
        bloc: BlocProvider.of<LoadingCubit>(context),
        builder: (context, loadingState) {
          return Center(
            child: Visibility(
                visible: BlocProvider.of<LoadingCubit>(context).state,
                child: const CircularProgressIndicator(
                  backgroundColor: Color(0xFF2C2C2C),
                )),
          );
        });
  }
}

loading cubit

class LoadingCubit extends Cubit<bool> {
  LoadingCubit() : super(true);

  toggleLoading() {
    emit(!state);
  }
}

loading button

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

  @override
  Widget build(BuildContext context) {
    return BlocBuilder<AutoLoginCubit, bool>(
      bloc: BlocProvider.of<AutoLoginCubit>(context),
      builder: (context, autoLoginState) => InkWell(
        child: Row(
          children: [
            Icon(
              autoLoginState == false
                  ? Icons.check_box_outline_blank
                  : Icons.check_box,
            ),
          ],
        ),
        onTap: () {
          BlocProvider.of<AutoLoginCubit>(context).toggleAutoLogin();
        },
      ),
    );
  }
}

button cubit

class AutoLoginCubit extends Cubit<bool> {
  AutoLoginCubit() : super(false){
    initState().then((value) => emit(value));
  }

  void toggleAutoLogin() async {
    if (state == false) {
      emit(true);
    } else {
      emit(false);
    }
    AutoLoginService().setAutoLoginState(state: state);
  }

  Future<bool> initState() async{
    return await AutoLoginService().getAutoLoginState();
  }
}

the page

Row(
 children:[
   BlocProvider(
       create: (context) => AutoLoginCubit(),
       child: const AutoLoginButton(),
       ),
   BlocProvider(
              create: (BuildContext context) => LoadingCubit(),
              child: const LoadingWidget()),
     ]
       )

Solution

  • You should use a MultiBlocProvider.

    The solution is :

    MultiBlocProvider(
     providers: [
        BlocProvider(create: (context) => AutoLoginCubit() ),
        BlocProvider(create: (context) => LoadingCubit() ),
     ],
     child: Row(
        children:[ AutoLoginButton(), LoadingWidget()]
     )
    )
    

    Explanation: Flutter forms a tree like structure (Similar to DOM in HTML) for its visual element. Cubit/Blocs are attached to the elements, in this node tree. And are available to all child of a given node.

    enter image description here

    To Make it visible Cubit muts be moved upper in heiarchy:

    enter image description here