Most of the examples and prevailing wisdom I see use a typical template for a Widget within a class, where ALL further widgets are created within the build
method (which I think can give a clarity of code, but setting this aside).
However, if the referenced widget is not going to change further, it still gets recreated every build call. Is there any actual issue with assigning this in an initState
or the class constructor and referencing it later ?
Trivialised example
// this partial from inside the build() method currently
Container(
padding: const EdgeInsets.only(bottom: 8.0),
child: Text(
'Oeschinen Lake Campground',
style: TextStyle(
fontWeight: FontWeight.bold,
),
),
),
to
// Now inside initState or class Constructor
myText = Text(
'Oeschinen Lake Campground',
style: TextStyle(
fontWeight: FontWeight.bold,
),
);
...
// Still inside build method (in fact this could also go inside the constructor ?)
Container(
padding: const EdgeInsets.only(bottom: 8.0),
child: myText
)
This is just for code that isn't based on a state reference.
Are there any downsides other than design/aesthetics to doing it this way ? Whilst this example is trivial, I keep thinking that maybe there are some performance/battery/headspace benefits to not keep having to rebuild non state based widgets when the app gets a lot more complex (I'm also aware I think that a Widget further up the tree may still call for a new object each time). However, I'm new to flutter/dart, so wary about some issues I haven't considered properly, or fundamentally misunderstood some aspects.
initState() is a method that is called once when the Stateful Widget is inserted in the widget tree. We generally override this method if we need to do some sort of initialization work like registering a listener because, unlike build(), this method is called once.
Overriding of initState() method performs initialization which depends on the location at which this object was inserted into the tree (like context) or on the widget used to configure this object (or widget). In simple terms, while a page in flutter gets created on screen, this method gets called at very first.
The initState() is a method that is called when an object for your stateful widget is created and inserted inside the widget tree. It is basically the entry point for the Stateful Widgets.
Flutter widgets are built using a modern framework that takes inspiration from React. The central idea is that you build your UI out of widgets. Widgets describe what their view should look like given their current configuration and state.
TL;DR: Don't.
First, let's see what Googler and Flutter engineer Matt Sullivan has to say about this topic:
With Flutter creating and destroying objects with great frequency, should developers take steps to limit this behavior? It’s not uncommon to see new Flutter developers create references to widgets they know will not change over time, and place them in state so that they won’t be destroyed and rebuilt.
Don’t do this.
In order to understand why this is a bad idea, you first of all need to understand that Widget
s do very little.
Because they usually just compose other Widget
s or instantiate RenderObject
s, they don't do the actual rendering; all the heavy lifting is done by RenderObject
s.
You can think of the Widget
s as super-lightweight "blueprints" for RenderObject
s.
Also note that RenderObject
s get heavily cached by the Flutter framework itself, so if you create some similar Widget
in consecutive builds, the underlying RenderObject
is automatically reused.
By caching your UI, you are effectively re-creating a functionality which Flutter's rendering pipeline provides out of the box.
Solely because of that, many people would argue the added complexity to your code isn't worth it.
"Okay then," you might think, "The performance benefit may be very very small, but it does exist, right?"
Actually, no.
That's because the underlying Dart runtime uses two types of garbage collectors: the Young Space Scavenger garbage collector for short-lived objects and the mark-sweep garbage collector for long-lived objects.
For a more detailed explanation about how they work, check out this article fittingly named "Don't Fear the Garbage Collector".
Basically, it says that the Young Space Scavenger is much faster than the mark-sweep collector and if an app doesn't adhere to the "weak generational hypothesis" which states that most objects die young, then the mark-sweeping will occur more often.
Put short, performance might actually get worse.
To sum it up, re-implementing a built-in Flutter feature while making your code less readable and your app slower is probably not the right way to go.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With