Flutter Web滚动GridView时出现‘Assertion failed:_pressedKeys.containsKey(event.physicalKey)’错误的求助
Flutter Web: GridView.builder滚动时出现KeyUpEvent断言错误且滚动卡顿
问题描述
我通过POST请求从API获取数据后,使用GridView.builder展示数据。在应用的Web版本中,数据能正常显示,但一旦开始滚动,调试控制台就会抛出KeyUpEvent断言错误,同时滚动变得非常卡顿,动画完全失效。
错误信息
════════ Exception caught by services library ═════════════════════════════════ 在平台消息回调期间抛出了以下断言: Assertion failed: ../…/services/hardware_keyboard.dart:441 _pressedKeys.containsKey(event.physicalKey) "A KeyUpEvent is dispatched, but the state shows that the physical key is not pressed. If this occurs in real application, please report this bug to Flutter. If this occurs in unit tests, please ensure that simulated events follow Flutter's event model as documented in `HardwareKeyboard`. This was the event: KeyUpEvent#6f053(physicalKey: PhysicalKeyboardKey#700e3(usbHidUsage: \"0x000700e3\", debugName: \"Meta Left\"), logicalKey: LogicalKeyboardKey#4b191(keyId: \"0x200000106\", keyLabel: \"Meta Left\", debugName: \"Meta Left\"), character: null, timeStamp: 0:01:32.201000, synthesized)" 抛出异常时的调用栈: dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 251:49 throw_ dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 29:3 assertFailed packages/flutter/src/services/hardware_keyboard.dart 441:46 <fn> packages/flutter/src/services/hardware_keyboard.dart 451:14 [_assertEventIsRegular] packages/flutter/src/services/hardware_keyboard.dart 543:5 handleKeyEvent packages/flutter/src/services/hardware_keyboard.dart 821:57 handleRawKeyMessage dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 84:54 runBody dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 123:5 _async packages/flutter/src/services/hardware_keyboard.dart 808:51 handleRawKeyMessage packages/flutter/src/services/platform_channel.dart 73:49 <fn> dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 84:54 runBody dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 123:5 _async packages/flutter/src/services/platform_channel.dart 72:58 <fn> packages/flutter/src/services/binding.dart 379:35 <fn> dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 84:54 runBody dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 123:5 _async packages/flutter/src/services/binding.dart 376:98 <fn> lib/_engine/engine/platform_dispatcher.dart 1034:13 invoke2 lib/ui/src/ui/channel_buffers.dart 25:5 invoke lib/ui/src/ui/channel_buffers.dart 65:7 push lib/ui/src/ui/channel_buffers.dart 130:16 push lib/_engine/engine/platform_dispatcher.dart 302:25 invokeOnPlatformMessage lib/_engine/engine/keyboard.dart 130:39 [_handleHtmlEvent] lib/_engine/engine/keyboard.dart 39:7 <fn> ═══════════════════════════════════════════════════════════════════════════════
相关代码
@override Widget build(BuildContext context) { return Container( child: Scaffold( body: Row( children: [ SideDrawer(), Container( padding: EdgeInsets.all(20), width: MediaQuery.of(context).size.width * 0.77, child: FutureBuilder<dynamic>( future: appList(), builder: (context, snapshot) { if (snapshot.data == null) { return Center( child: CircularProgressIndicator(), ); } else { return GridView.builder( gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 5, childAspectRatio: 3 / 2, crossAxisSpacing: 10, mainAxisSpacing: 10), itemCount: snapshot.data.length - 1, itemBuilder: (context, index) { return Card( elevation: 2, child: ListTile( leading: Text(snapshot.data[index]["title"]), ), ); }, ); } }, ), ), ], ), ), ); }
解决方案
1. 升级Flutter到最新稳定版
这个KeyUpEvent断言错误是Flutter Web在旧版本中的已知bug,已经在后续的稳定版中修复。执行以下命令升级:
flutter upgrade
2. 优化FutureBuilder的使用方式
你当前在FutureBuilder的future参数中直接调用appList(),这会导致每次build方法执行时都重新发起API请求,不仅浪费资源,还会引发不必要的组件重建,加剧滚动卡顿。
修改方法:在initState中初始化Future,避免重复请求:
late Future<dynamic> _appListFuture; @override void initState() { super.initState(); // 只在组件初始化时发起一次请求 _appListFuture = appList(); } @override Widget build(BuildContext context) { return Container( child: Scaffold( body: Row( children: [ SideDrawer(), Container( padding: EdgeInsets.all(20), width: MediaQuery.of(context).size.width * 0.77, child: FutureBuilder<dynamic>( future: _appListFuture, // 使用初始化好的Future builder: (context, snapshot) { // ... 原有代码保持不变 }, ), ), ], ), ), ); }
3. 修复GridView的布局约束问题
你的GridView嵌套在Row的Container中,没有明确的高度约束,这会导致Flutter在滚动时反复计算布局,引发卡顿。可以通过以下两种方式解决:
方式一:用Expanded替代Container
将包裹FutureBuilder的Container替换为Expanded,让它自动填充Row的剩余空间,同时给GridView提供明确的高度约束:Expanded( child: Padding( padding: EdgeInsets.all(20), child: FutureBuilder<dynamic>( future: _appListFuture, builder: (context, snapshot) { // ... 原有代码保持不变 }, ), ), )方式二:给Container设置明确高度
如果需要固定宽度,可以给Container添加高度约束:Container( padding: EdgeInsets.all(20), width: MediaQuery.of(context).size.width * 0.77, height: MediaQuery.of(context).size.height, // 填充屏幕高度 child: FutureBuilder<dynamic>( // ... 原有代码保持不变 ), )
4. 可选:优化GridView的性能
如果数据量较大,可以添加addAutomaticKeepAlives: false和addRepaintBoundaries: false来减少不必要的组件重建(根据实际情况调整,若Card内容复杂可能需要保留):
GridView.builder( addAutomaticKeepAlives: false, addRepaintBoundaries: false, gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 5, childAspectRatio: 3 / 2, crossAxisSpacing: 10, mainAxisSpacing: 10, ), // ... 其他参数保持不变 )
内容的提问来源于stack exchange,提问作者lordarcadius
相关产品推荐
相关产品推荐

