键盘打开时关闭EndDrawer抛出Widget已卸载异常求助
问题:关闭打开键盘的EndDrawer时触发组件已卸载异常
当键盘处于打开状态时关闭EndDrawer会触发如下断言异常,键盘未聚焦时无此问题。抽屉内包含SearchField组件,本不应出现该错误。
异常信息
======== Exception caught by widgets library ======================================================= The following assertion was thrown building StreamBuilder<List<SearchFieldListItem<dynamic>?>?>(dirty, state: _StreamBuilderBaseState<List<SearchFieldListItem<dynamic>?>?, AsyncSnapshot<List<SearchFieldListItem<dynamic>?>?>>#75ea8): This widget has been unmounted, so the State no longer has a context (and should be considered defunct).
相关代码
appBar: AppBar(title: Text('XYZ')), endDrawer: Drawer( child: ListView( children: [ Padding( padding: EdgeInsets.all(10), child: SizedBox( child: const DrawerHeader( child: Text('Filter'), ), ), ), Padding( padding: EdgeInsets.all(10), child: Container( child: SearchField<Model>( onSuggestionTap: (buyerValue) {}, ), ), ), ], ), ), body: Container(),
解决方案
方法1:主动取消SearchField的焦点
通过给SearchField绑定FocusNode,在抽屉关闭时主动取消焦点,避免键盘未收起导致组件状态异常更新:
- 定义FocusNode:
final FocusNode _searchFocusNode = FocusNode(); - 给SearchField绑定FocusNode:
SearchField<Model>( focusNode: _searchFocusNode, onSuggestionTap: (buyerValue) {}, ), - 在Scaffold中监听抽屉状态,关闭时取消焦点:
Scaffold( // ...其他配置项 onEndDrawerChanged: (isOpen) { if (!isOpen) { _searchFocusNode.unfocus(); } }, endDrawer: // ...你的抽屉代码 )
方法2:在StreamBuilder中判断组件挂载状态
如果可以修改SearchField内部的StreamBuilder逻辑,在构建UI前先判断组件是否仍处于挂载状态,避免卸载后触发状态更新:
StreamBuilder<List<SearchFieldListItem<dynamic>?>?>( stream: // 原数据流配置 builder: (context, snapshot) { // 先校验组件挂载状态 if (!context.mounted) return const SizedBox.shrink(); // 原有的UI构建逻辑 }, )
方法3:关闭抽屉前强制隐藏键盘
在触发抽屉关闭的操作前,先主动隐藏键盘,确保组件状态稳定后再关闭抽屉:
// 示例:关闭按钮的点击事件 onPressed: () { FocusManager.instance.primaryFocus?.unfocus(); Navigator.of(context).pop(); }
内容的提问来源于stack exchange,提问作者Neev Shah
相关产品推荐
相关产品推荐

