Flutter使用Bloc+freezed实现底部弹窗仅首次点击生效问题咨询
问题根因
- Bloc默认开启连续相同状态过滤逻辑:首次点击浮动按钮时,Bloc状态从
NoteState.initial()切换为NoteState.addNoteClickedState(),状态发生变更触发listener弹出底部弹层。但你的逻辑中没有将状态切回初始值,后续点击浮动按钮时,Bloc收到事件后再次yield相同的NoteState.addNoteClickedState(),Bloc判定状态未发生变化,不会触发listener回调,因此第二次点击无响应。 - 额外潜在问题:
GlobalKey<ScaffoldState>定义在build方法内部,每次页面重建都会生成新的key,可能引发Scaffold操作相关异常。
解决方案
推荐使用状态复位方案,修改Bloc逻辑,触发弹层后立即将状态切回初始值,保证后续点击可以再次触发状态变更:
1. 修改Bloc代码
class NoteBloc extends Bloc<NoteEvent, NoteState> { NoteBloc() : super(const _Initial()); @override Stream<NoteState> mapEventToState( NoteEvent event, ) async* { if(event is AddNoteClickedEvent){ yield const AddNoteClickedState(); // 立即切回初始状态,为下一次点击做准备 yield const NoteState.initial(); } } }
2. 调整页面代码,修正GlobalKey的定义位置
将GlobalKey从build方法移出,改为存储在State中:
class HomePage extends StatefulWidget { const HomePage({super.key}); @override State<HomePage> createState() => _HomePageState(); } class _HomePageState extends State<HomePage> { final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>(); @override Widget build(BuildContext context) { return BlocConsumer<NoteBloc, NoteState>( listener: (context, state) { state.maybeMap( orElse: () {}, addNoteClickedState: (_) { _scaffoldKey.currentState!.showBottomSheet( (context) => const AddNewNoteBottomSheet(), ); }, ); }, builder: (context, state) { return Scaffold( key: _scaffoldKey, floatingActionButton: InkWell( onTap: () { context.read<NoteBloc>().add(const NoteEvent.addNoteClickedEvent()); }, child: Icon( Icons.add, color: const Color(whiteColor), size: 9.h, ), ), ); }, ); } }
内容的提问来源于stack exchange,提问作者Mariam Albarghouti
相关产品推荐
相关产品推荐

