9

I noticed that the build function was called twice in a stateless widget.

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")),
    );
  }
}

console result

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

From the console output, the constructor was called once and the build function was called twice.

I searched this issue and read documents below.

Why Root Widget gets build twice?

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

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

However, I don't understand clearly. Why is the build function called multiple times? I'm not using async or future, and my code is very simple.

This problem does not occur when running on dartpad. It only occurs in android studio.

battlecook
  • 471
  • 6
  • 17

2 Answers2

9

The build method might get called multiple times due to a number of reasons. It should not be considered a problem, just how Flutter works.

The Widget.build documentation states:

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.

Also there is this response from the Flutter team on a similar closed issue on 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.

Azbuky
  • 1,714
  • 1
  • 12
  • 6
1

As answered by Azbuky, the Flutter team decides when to call the build method., but we can expect that each of those calls are valid ones. Therefore, they can be avoided and this is how I did solve it, by using the ReactiveBuilder from rx_widgets package:

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();
        });
  }
}

4F2E4A2E
  • 1,964
  • 26
  • 28