为什么在热重启时构建函数会被调用两次?

13

我注意到无状态小部件中的构建函数被调用了两次。

import 'package:flutter/material.dart';

void main() {
  runApp(new MyApp());
}

class MyApp extends StatelessWidget {
  MyApp() {
    print("constructor MyApp class");
  }

  @override
  Widget build(BuildContext context) {
    print("build MyApp");
    return MaterialApp(
      home: HomeWidget(),
    );
  }
}

class HomeWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(child: Text("home widget")),
    );
  }
}

控制台结果

Performing hot restart...
Syncing files to device AOSP on IA Emulator...
Restarted application in 755ms.
I/flutter (14765): constructor MyApp class
I/flutter (14765): build MyApp
I/flutter (14765): build MyApp

从控制台输出来看,构造函数被调用了一次,而 build 函数被调用了两次。

我搜索了这个问题并阅读了以下文件。

为什么根 Widget 会被构建两次?

https://github.com/flutter/flutter/issues/33566

https://flutterigniter.com/future-async-called-multiple-times/

然而,我还是不太理解。为什么 build 函数会被多次调用?我没有使用 async 或 future,我的代码非常简单。

在 dartpad 上运行时,这个问题不会出现。它只在 Android Studio 上出现。

2个回答

11

由于多种原因,build方法可能会被调用多次。这不应该被视为问题,它只是Flutter的工作方式。

Widget.build文档中指出:

当给定BuildContext的树中插入此widget时以及此widget的依赖关系发生更改时,框架将调用此方法。[...]此方法可能在每个帧中都被调用,除了构建widget之外,不应该有任何副作用。

此外,在GitHub上类似已关闭问题的 Flutter团队回应 中也有这句话:

Flutter不能保证最少次数地调用Widget.build。您应该以假设build在每个帧上被调用的方式来构建您的应用程序 - 任何少于此数量的调用都是一种优化。


2
如Azbuky所回答的那样,Flutter团队决定何时调用build方法。但我们可以期望每个调用都是有效的。 因此,它们是可以避免的,这就是我如何解决它的方法,使用rx_widgets包中的ReactiveBuilder
class App extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return ReactiveBuilder(
        // Pass in a stream
        stream: Firebase.initializeApp().asStream().take(1),
        builder: (BuildContext context, _) {
          // Return your widgets
          return Container();
        });
  }
}


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接