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

bat*_*ook 14 flutter

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

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")),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

控制台结果

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
Run Code Online (Sandbox Code Playgroud)

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

我搜索了这个问题并阅读了下面的文档。

为什么 Root Widget 需要构建两次?

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

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

不过,我不太明白。为什么构建函数被多次调用?我没有使用 async 或 future,而且我的代码非常简单。

在dartpad上运行时不会出现此问题。它只发生在android studio中。

小智 12

由于多种原因,构建方法可能会被多次调用。这不应该被认为是一个问题,只是 Flutter 的工作原理而已。

Widget.build文档指出:

The framework calls this method when this widget is inserted into the tree in a given BuildContext and when the dependencies of this widget change. [...] This method can potentially be called in every frame and should not have any side effects beyond building a widget.

Flutter 团队对 GitHub 上的类似已关闭问题也做出了回应:

Flutter does not guarantee Widget.build will be called the minimum number of times possible. You should structure your application in a way that assumes build will be called on every frame - anything less is an optimization.