You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter中Firebase.initializeApp的FutureBuilder两次触发ConnectionState.done

问题原因

你遇到的ConnectionState.done触发两次的问题,由两个常见原因导致:

  1. 组件树结构设计错误:你当前代码里Loading和MyHome两个分支都各自返回独立的MaterialApp实例。当Future完成后,Flutter需要替换整棵MaterialApp子树,这个过程会触发上层_AppState重新执行build方法,此时_initialization已经是完成状态,会再次命中done分支产生第二次打印。
  2. 小概率的Firebase Core内部逻辑:FlutterFire的初始化方法完成后,内部会同步更新一次全局实例状态,也可能触发FutureBuilder的回调重复执行。

另外你代码的错误分支没有加return语句,属于隐藏bug,需要同步修复。

修复方案

第一步:调整顶层组件结构,把MaterialApp提到FutureBuilder外层

修改_AppState的代码如下:

class _AppState extends State<App> {
  final Future<FirebaseApp> _initialization = Firebase.initializeApp();

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: FutureBuilder(
        future: _initialization,
        builder: (context, snapshot) {
          if (snapshot.hasError) {
            // 补充return逻辑
            return Scaffold(
              body: Center(child: Text("初始化出错:${snapshot.error}"))
            );
          }
          if (snapshot.connectionState == ConnectionState.done) {
            print("Initialize Firebase Done!!");
            return MyHome();
          }
          return Loading();
        },
      ),
    );
  }
}

第二步:移除子组件里多余的MaterialApp

修改Loading组件代码,去掉外层MaterialApp包裹:

class Loading extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Text("Loading..."),
      ),
    );
  }
}

修改MyHome组件代码,同样去掉外层MaterialApp:

class MyHome extends StatefulWidget {
  @override
  _MyHomeState createState() => _MyHomeState();
}

class _MyHomeState extends State {
  @override
  void initState() {
    FirebaseAuth
        .instance
        .idTokenChanges()
        .listen((User? user) {
          if (user == null) {
            print('User is signed out');
          } else {
            print('User is signed in!.' + user.displayName!);
          }
       });
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Text('hello'),
    );
  }
}

额外说明

调整完成后绝大多数场景下只会触发一次done分支的打印。如果仍有偶发的两次打印也无需担心,因为你已经将初始化Future缓存到了State中,不会重复执行Firebase初始化逻辑,只是build方法的正常重入,没有性能问题和副作用。


内容的提问来源于stack exchange,提问作者Jinhong Kim

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.10 09:24:03