Flutter Cubit内部布尔值修改及状态控制Widget显示实现问题
存在的问题
- 状态设计错误:你当前的Cubit继承自
Cubit<bool>,仅支持单个布尔值作为全局状态,但你需要控制两个独立的布尔变量one、two,且这两个变量定义为Cubit的类属性,没有纳入状态管理范围,调用emit不会触发这两个属性的更新。 - Dart值传递特性限制:你在
changeValue方法中传入布尔参数,修改的只是方法内的局部变量副本,根本不会修改Cubit类中的one、two属性。 - 每次主动创建新的Cubit实例:
BlocBuilder和点击事件中都写了ChangeBoolCubit().one,这里每次都会新建一个独立的Cubit实例,拿到的永远是初始值,和你通过BlocProvider挂载在上下文的实例完全无关,也不会响应状态更新。 - 没有使用BlocBuilder提供的state参数:BlocBuilder的builder回调已经返回了最新的状态值,你完全没有用到这个参数,反而自己新建实例拿属性,自然不会更新。
修复实现
首先定义包含两个布尔值的状态类,支持拷贝更新:
class BoolState { final bool one; final bool two; BoolState({required this.one, required this.two}); // 拷贝方法,方便修改指定属性生成新状态 BoolState copyWith({ bool? one, bool? two, }) { return BoolState( one: one ?? this.one, two: two ?? this.two, ); } }
修改Cubit定义,继承自Cubit<BoolState>:
class ChangeBoolCubit extends Cubit<BoolState> { // 初始状态one为false,two为true ChangeBoolCubit() : super(BoolState(one: false, two: true)); // 切换one的值 void toggleOne() { emit(state.copyWith(one: !state.one)); } // 切换two的值 void toggleTwo() { emit(state.copyWith(two: !state.two)); } }
修改页面View代码,使用BlocBuilder返回的state参数,调用正确的实例方法:
class BoolView extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('Changing Bool')), body: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ Center( child: BlocBuilder<ChangeBoolCubit, BoolState>( builder: (context, state) { // 直接用回调返回的state拿最新值 return state.one ? Text('TRUE: ${state.one}') : Text('FALSE: ${state.one};'); }, ), ), Center( child: BlocBuilder<ChangeBoolCubit, BoolState>( builder: (context, state) { return state.two ? Text('TRUE: ${state.two}') : Text('FALSE: ${state.two};'); }, ), ), ], ), floatingActionButton: Column( mainAxisAlignment: MainAxisAlignment.end, crossAxisAlignment: CrossAxisAlignment.end, children: <Widget>[ FloatingActionButton( child: const Icon(Icons.add), // 调用上下文挂载的Cubit实例的toggleOne方法 onPressed: () => context.read<ChangeBoolCubit>().toggleOne(), ), const SizedBox(height: 8), FloatingActionButton( child: const Icon(Icons.remove), // 调用上下文挂载的Cubit实例的toggleTwo方法 onPressed: () => context.read<ChangeBoolCubit>().toggleTwo(), ), ], ), ); } }
最后别忘了在BoolView的父组件中添加BlocProvider挂载Cubit实例:
BlocProvider( create: (context) => ChangeBoolCubit(), child: BoolView(), )
内容的提问来源于stack exchange,提问作者mmcib
相关产品推荐
相关产品推荐

