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

发布于 2025-01-10 15:06:56 字数 2352 浏览 6 评论 0原文

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

加载小部件

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()),
     ]
       )

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()),
     ]
       )

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

美羊羊 2025-01-17 15:06:56

您应该使用 MultiBlocProvider

解决办法是:

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

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

输入图片此处描述

要使其可见,肘节必须在层次结构中向上移动:

在此处输入图像描述

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

烏雲後面有陽光 2025-01-17 15:06:56

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

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

You need to toggle loading on your AutoLoginButton onTap function with BlocProvider.of<LoadingCubit>(context).toggleLoading(); to trigger rebuild of loading widget, but to be able to call toggleLoading() on LoadingCubit you need to provide it above your AutoLoginButton. So my solution for this would be:

MultiBlocProvider(
          providers: [
            BlocProvider(create: (context) => AutoLoginCubit()),
            BlocProvider(create: (BuildContext context) => LoadingCubit()),
          ],
          child: Row(
            children: [
              const AutoLoginButton(),
              const LoadingWidget(),
            ],
          ),
        ),
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文