Flutter热重载时FutureBuilder触发两次导致报错如何解决?
问题根因
你当前代码的核心问题是直接在FutureBuilder的future参数中调用frameFuture()方法,每次widget触发build时都会生成一个全新的Future实例:
首次启动时页面仅执行1次build,因此Future只会执行一次,符合预期;热重载会强制触发widget重建、重新执行build方法,就会生成新的Future实例,导致Future被多次执行、builder回调触发两次,最终引发报错。
修复方案
只需要缓存Future实例,避免每次build重复创建即可,修改步骤如下:
- 在State类中声明一个Future类型的私有变量,用来缓存初始化的异步任务
- 在
initState中完成该Future变量的初始化,initState在整个State生命周期内只会执行1次,热重载也不会重复触发 - 将
FutureBuilder的future参数绑定到缓存的变量上,禁止直接在参数位调用异步方法
修复后代码示例
// 先在State类中定义缓存Future的变量 late Future _frameFuture; Future frameFuture() async { // 可选优化:用Future.wait并行执行两个异步请求,比串行await速度更快 return Future.wait([ AuthService.getUserDataFromFirestore(), GeoService.getPosition() ]); } @override void initState() { user = FirebaseAuth.instance.currentUser!; // 仅在initState中初始化一次Future _frameFuture = frameFuture(); super.initState(); } @override Widget build(BuildContext context) { return FutureBuilder( // 绑定缓存的Future变量,不要直接调用frameFuture() future: _frameFuture, builder: (context, snap) { // 可选优化:增加错误处理逻辑,避免异常时页面卡死 if (snap.hasError) { // 可替换为你的错误提示组件 return Center(child: Text('加载失败:${snap.error}')); } if (snap.connectionState == ConnectionState.done && snap.hasData) return HomePage(); else return Container( color: Colors.black, child: Center( child: spinKit, ), ); } ); }
补充说明
如果你的业务逻辑需要在热重载时重新执行该初始化异步任务,仅需修改代码后执行冷重启即可,上述修改不会影响正常的业务初始化逻辑。
内容的提问来源于stack exchange,提问作者RyanBuss01
相关产品推荐
相关产品推荐

