如何通过Key强制Flutter Stateful Widget完成重绘?
问题根源
你当前的写法有三个核心错误导致Key触发重绘不生效:
- 你将
dataView定义为全局final常量,实例一旦创建就不会再变更,即使你修改了外部redraw变量,也不会同步到已经创建好的view实例的Key属性上,自然无法触发Widget重建 - 你直接修改StatefulWidget的成员变量,没有在State层调用
setState方法通知Flutter框架重绘 Key触发State重建的前提是同一位置的Widget实例被替换为携带不同Key的新实例,你没有替换Widget实例,仅修改外部变量无法触发逻辑
解决方案
方案1:修正Key触发重建的写法
如果要继续使用你原本的Key换State的逻辑,只需要调整实例创建方式即可:
- 不要提前创建全局
dataView实例,将redraw和计数器变量放到你首页的State类中 - 在
build方法中动态创建view实例,每次setState后都会传入新的Key触发重建
示例代码:
// 首页State类内定义变量 Object redraw = Object(); int count = 0; // build方法中动态构建Widget @override Widget build(BuildContext context) { return Scaffold( body: Center( child: view( key: ObjectKey(redraw), count: count, ) ), floatingActionButton: FloatingActionButton( child: Icon(Icons.badge), onPressed: (){ setState((){ count++; redraw = Object(); }); }, ), ); }
方案2:更符合Flutter设计规范的实现(推荐)
Flutter是响应式框架,不推荐用强制换Key销毁重建的方式更新UI,你可以通过State暴露更新方法或者上层状态驱动的方式实现重绘:
- 给你的
view组件的State暴露更新方法,内部调用setState触发重绘
class _viewState extends State<view>{ @override Widget build(BuildContext context) { return Text("Counter: ${widget.count}"); } // 暴露更新方法 void incrementCounter() { setState(() { widget.count++; }); } // 如果需要从外部更新数据也可以加对应方法 void updateData(String action, dynamic params, dynamic data) { setState(() { widget._action = action; widget._actionParams = params; widget._data = data; }); } }
- 上层通过
GlobalKey获取State实例调用更新方法即可
// 首页定义GlobalKey final viewKey = GlobalKey<_viewState>(); // build时传入Key body: Center(child: view(key: viewKey, count: 0)) // 点击按钮时调用更新 onPressed: (){ viewKey.currentState?.incrementCounter(); }
其他疑问说明
- 你当前的组件可以直接和Navigator结合使用,不需要切换到其他开发范式,只需要将
view组件作为路由页面传入Navigator.push即可正常支持返回按钮逻辑 - 注意Dart规范中类名需要使用大驼峰命名,建议你将
view类重命名为View避免后续编译问题
内容的提问来源于stack exchange,提问作者TTR
相关产品推荐
相关产品推荐

