Flutter: StatelessWidget.build called multiple times [duplicate]
Asked Answered
B

1

8

I always put code in my questions here, but this time it's not possible since the bug could be anywhere in a thousand lines of code. However:

I noticed that the build method of my main screen (StatelessWidget), which is a descendant of a MaterialApp (home property), get's as usual called once while in debug mode but three times when in release mode.

Under which circumstances could such a thing happen? I already tried reproducing multiple times, but failed.

EDIT:

The problem is that I am storing the screen size that I get from a media query as a global variable, so that I can access it from anywhere. Now I need to access that variable inside the init method of a stateful widget further down the tree. Seems to be no problem in debug mode, but in release mode the build method of the widget that makes the media query (must be inside build) weirdly gets called one time, the result of the media query being a Size(0.0, 0.0), then the init method of the widget further down the tree gets called and then the build method with the media query gets called another two times (this time with the correct screen size). The result is that I don't have he correct screen size inside the init method.

Beriberi answered 9/11, 2018 at 9:55 Comment(9)
What issues are you getting being caused by the build method being called multiple times?Freud
Good that you ask. Should have provided that information in the question:Beriberi
build() being called multiple times is expected. For instance when the keyboard pops up the screen size changes multiple times during the animation. Each frame build() of your root widget and all its descendants are called to allow them to adjust the view to the new screen size.Tudela
@GünterZöchbauer okay, thank you. I understand that. Do you have an idea how I could solve the problem with the media query (screen size) in a global variable?Beriberi
Use a StreamController instead of a field then anyone interested can subscribe (listen) to mediaquery changes.Tudela
@GünterZöchbauer Thank you, that sounds like a good idea. I fiddled with Streams and StreamBuilder a few days ago. Would you say that this kind of structure is overall better for providing states to different parts of the app than scoped model? Currently I am using the latter as some kind of state manager which is wrapped around the root and has fields containing every other model. Sorry for going off topic here.Beriberi
The problem is that I am storing the screen size that I get from a media query as a global variable, so that I can access it from anywhere. That souds like a bad idea. The reason why Flutter uses the everything is a widget sentence is to avoid this kind of thingsMartinic
@RémiRousselet Okay. I'll keep that in mind. But how would one go about getting the screen size from within init()? Or is that also a bad idea? I couldn't figure out how to provide a ScrollController with the screen size that it depends on.Beriberi
StatfulWidget's didChangeDependencies is here for that. You can combine it with MediaQuery.of(context)Martinic
O
12

https://docs.flutter.io/flutter/widgets/FutureBuilder-class.html

The future must have been obtained earlier, e.g. during State.initState, State.didUpdateConfig, or State.didChangeDependencies. It must not be created during the State.build or StatelessWidget.build method call when constructing the FutureBuilder. If the future is created at the same time as the FutureBuilder, then every time the FutureBuilder's parent is rebuilt, the asynchronous task will be restarted.

A general guideline is to assume that every build method could get called every frame, and to treat omitted calls as an optimization.

(taken from https://github.com/flutter/flutter/issues/27847#issuecomment-462868299)

Ostend answered 11/4, 2019 at 7:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.