Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Defining widgets inside initState or class constructors rather than build?

Tags:

flutter

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.

like image 837
Ian Avatar asked Oct 17 '18 13:10

Ian


People also ask

Is initState called before build flutter?

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.

How do I override initState flutter?

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.

What is initState in flutter?

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.

What does Widget build do in flutter?

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.


1 Answers

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 Widgets do very little. Because they usually just compose other Widgets or instantiate RenderObjects, they don't do the actual rendering; all the heavy lifting is done by RenderObjects. You can think of the Widgets as super-lightweight "blueprints" for RenderObjects.
Also note that RenderObjects 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.

like image 79
Marcel Avatar answered Sep 21 '22 23:09

Marcel