Flutter中Cubit结合Stepper组件实现Radio/Dropdown状态更新
核心逻辑
Cubit 状态管理的核心是通过事件触发状态变更,UI 监听状态自动重建。针对 Radio、DropdownButton 这类交互选择组件,需遵循以下流程:
- 定义包含选中状态的不可变状态类
- 在 Cubit 中实现处理选择事件的方法
- UI 层通过
BlocBuilder绑定状态,渲染组件并触发事件
完整示例代码
1. 定义 Cubit 与状态类
import 'package:flutter_bloc/flutter_bloc.dart'; // 状态类:保存Radio和Dropdown的选中值 class SelectionState { final String selectedRadio; final String selectedDropdown; const SelectionState({ required this.selectedRadio, required this.selectedDropdown, }); // 生成新状态的复制方法(遵循不可变状态原则) SelectionState copyWith({ String? selectedRadio, String? selectedDropdown, }) { return SelectionState( selectedRadio: selectedRadio ?? this.selectedRadio, selectedDropdown: selectedDropdown ?? this.selectedDropdown, ); } } // Cubit类:处理选择事件并更新状态 class SelectionCubit extends Cubit<SelectionState> { SelectionCubit() : super(const SelectionState( selectedRadio: 'option1', // 默认选中项 selectedDropdown: 'item1', )); // 更新Radio选中状态 void updateRadio(String value) { emit(state.copyWith(selectedRadio: value)); } // 更新Dropdown选中状态 void updateDropdown(String value) { emit(state.copyWith(selectedDropdown: value)); } }
2. UI 层实现(绑定Cubit与组件)
import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; class SelectionPage extends StatelessWidget { const SelectionPage({super.key}); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('Cubit 选择组件示例')), body: Padding( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Radio 组件组 const Text('Radio 选项'), BlocBuilder<SelectionCubit, SelectionState>( builder: (context, state) { return Column( children: [ RadioListTile( title: const Text('选项1'), value: 'option1', groupValue: state.selectedRadio, onChanged: (value) { if (value != null) { context.read<SelectionCubit>().updateRadio(value); } }, ), RadioListTile( title: const Text('选项2'), value: 'option2', groupValue: state.selectedRadio, onChanged: (value) { if (value != null) { context.read<SelectionCubit>().updateRadio(value); } }, ), ], ); }, ), const SizedBox(height: 20), // DropdownButton 组件 const Text('Dropdown 选项'), BlocBuilder<SelectionCubit, SelectionState>( builder: (context, state) { return DropdownButton<String>( value: state.selectedDropdown, items: const [ DropdownMenuItem(value: 'item1', child: Text('项目1')), DropdownMenuItem(value: 'item2', child: Text('项目2')), DropdownMenuItem(value: 'item3', child: Text('项目3')), ], onChanged: (value) { if (value != null) { context.read<SelectionCubit>().updateDropdown(value); } }, isExpanded: true, ); }, ), const SizedBox(height: 20), // 实时展示选中状态 BlocBuilder<SelectionCubit, SelectionState>( builder: (context, state) { return Text( '当前选中:Radio=${state.selectedRadio},Dropdown=${state.selectedDropdown}', style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold), ); }, ), ], ), ), ); } }
3. 注入 Cubit(父Widget中)
void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return BlocProvider( create: (context) => SelectionCubit(), child: MaterialApp( home: const SelectionPage(), ), ); } }
关键注意事项
- 不可变状态:状态类必须不可变,通过
copyWith生成新状态,禁止直接修改原状态 - 精准重建:仅用
BlocBuilder包裹需要更新的组件,避免全局重建浪费性能 - 事件触发:组件的
onChanged回调中,通过context.read<Cubit>()获取实例并调用事件方法,不要直接操作状态 - 默认值初始化:Cubit 初始状态需设置合理默认选中值,避免UI出现空状态异常
内容的提问来源于stack exchange,提问作者Saeed Alskaf
相关产品推荐
相关产品推荐

