【问题标题】:Flutter - FutureBuilder fires twice on hot reloadFlutter - FutureBuilder 在热重载时触发两次
【发布时间】:2021-12-26 05:46:12
【问题描述】:

在我的颤振项目中,当我在模拟器中启动项目时,一切正常,未来的构建器只触发一次,但是当我热重载时,FutureBuilder 触发两次,这会导致错误,知道如何解决这个问题吗?

  Future frameFuture()  async {
    var future1 = await AuthService.getUserDataFromFirestore();
    var future2 = await GeoService.getPosition();
    return [future1, future2];
  }

  @override
  void initState() {
    user = FirebaseAuth.instance.currentUser!;
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return FutureBuilder(
        future: frameFuture(),
        builder: (context, snap) {
          if (snap.connectionState == ConnectionState.done && snap.hasData) return HomePage();
          else return Container(
            color: Colors.black,
            child: Center(
              child: spinKit,
            ),
          );
        }
    );
  }

【问题讨论】:

    标签: flutter dart future flutter-futurebuilder


    【解决方案1】:

    您已经想到的解决方案是将未来的加载过程移至 StatefulWidget 的 initState,但我将解释它发生的原因: 你在你的构建方法中调用你的未来是这样的:

      @override
      Widget build(BuildContext context) {
        return FutureBuilder(
            future: frameFuture(),
    

    问题是 Flutter 每次渲染 Widget 时都会调用 build 方法,每当依赖项发生变化(InheritedWidget, setState)或 Flutter 决定重建它时。因此,每次重绘 UI frameFuture() 时都会被调用,这会使您的构建方法产生不应有的副作用(此异步调用),并且鼓励小部件不要产生副作用。

    通过将异步计算移至initState,您只需调用一次,然后从您的状态访问缓存的变量futures

    这里是FutureBuilder class文档的摘录

    "future 必须在较早的时候获得,例如在 State.initState、State.didUpdateWidget 或 State.didChangeDependencies 期间。在构造 FutureBuilder 时,不能在 State.build 或 StatelessWidget.build 方法调用期间创建它。如果future 与 FutureBuilder 是同时创建的,那么每次 FutureBuilder 的 parent 重建时,都会重新启动异步任务。”

    希望这能说明解决方案的原因

    【讨论】:

      【解决方案2】:

      我解决了这个问题。我将Future 函数放在initState 中,然后在FutureBuilder 中使用变量。我不确定为什么它会这样工作,但这里是代码:

        var futures;
      
        Future frameFuture()  async {
          var future1 = await AuthService.getUserDataFromFirestore();
          var future2 = await GeoService.getPosition();
          return [future1, future2];
        }
      
        @override
        void initState() {
          user = FirebaseAuth.instance.currentUser!;
          super.initState();
          futures = frameFuture();
        }
      
        @override
        Widget build(BuildContext context) {
          return FutureBuilder(
              future: futures,
              builder: (context, snap) {
                if (snap.connectionState == ConnectionState.done && snap.hasData) return HomePage();
                else return Container(
                  color: Colors.black,
                  child: Center(
                    child: spinKit,
                  ),
                );
              }
          );
        }
      

      【讨论】:

        猜你喜欢
        • 2020-02-08
        • 1970-01-01
        • 1970-01-01
        • 2022-11-28
        • 2019-03-21
        • 1970-01-01
        • 2019-07-30
        相关资源
        最近更新 更多