使用 Cubit Bloc 从另一个小部件更新小部件

Update a widget from another one with Cubit Bloc

我在屏幕上有两个小部件,一个加载小部件和一个按钮小部件我想在每次点击按钮时更改加载小部件的状态。

正在加载小部件

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),
                )),
          );
        });
  }
}

加载肘

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

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

加载按钮

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();
        },
      ),
    );
  }
}

纽扣肘

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();
  }
}

页面

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

你应该使用 MultiBlocProvider.

解决方法是:

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

说明: Flutter 为其视觉元素形成了一个树状结构(类似于 HTML 中的 DOM)。 Cubit/Blocs 附加到此节点树中的元素。 并且对给定节点的所有子节点可用。

要使其可见,必须将 Cubit 移到层次结构的上层:

您需要使用 BlocProvider.of<LoadingCubit>(context).toggleLoading(); 在 AutoLoginButton onTap 函数上切换加载以触发加载小部件的重建,但为了能够在 LoadingCubit 上调用 toggleLoading() 您需要提供它在你的 AutoLoginButton 之上。所以我的解决方案是:

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