Not really sure what is the question here, and the referenced docs comment on this topic, but
This code defines a widget that spins a green square continually. It is built with an AnimatedBuilder and makes use of the child feature to avoid having to rebuild the Container each time.
Imagine you would rotate some heavy widget, like your whole app. You only want to change the roration using the Transform widget, but the child (the whole app in this case) does nothing based on the animation and therefore does not need to do any more builds. By removing the child and putting everything to builder, you make the framework build the entire stuff in builder every tick of the animation. In general, we should aim to minimazing unnecessary buildings and painting of widgets with things like moving things that don’t depend on animation to child, putting those BlocBuilders etc. as deep as possible, etc.
Totally agree with not making the framework build all the stuff, every tick of the animation.
But my main question is about whether there’s any difference between storing a widget instance as a local variable in the outer build() function vs. using the child parameter.
Here’s a DartPad sample that’s either built once total or once each frame, depending on whether a callback is invoked inside or outside the ValueListenableBuilder. Hopefully it shows that setting the child parameter isn’t necessary for preventing rebuilds.
I think putting the widget in the child argument is just clearer for average developer to use then doing cahing in variable etc in widget’s field or variable.
Awesome thread, I was wondering about that myself many times in the past.
So ideally the content of the child parameter won’t get necessarily get rebuild when the builders content is rebuild?
Yeah, any time a widget instance is identical to the previous instance (either by using const constructors or by caching the value somewhere) the widget won’t be rebuilt.
Using an AnimatedBuilder makes it easy to cache the widget value!
There is one downside for assigning a widget to a variable: you can put it in multiple places by mistake, and this is NOT allowed (especially for a non-const widget, such as Container).
Also, it is not the declaration that counts (there is no difference whatsoever to pass a variable or a widget to a child property: it run build when needed for both cases). This is only not true for static widgets (with const constructors). They will be rendered only once (but can still be composed on screen rotated, etc.)
Adding the same non-const widget instance to multiple places usually won’t cause any problems. The only exception is when it leads to “duplicate key” errors, but even with identical Key configurations, it usually won’t be an issue.
It’s true that the child parameter can be convenient for reducing the scope of the child widget. Seeing as it’s too late to change the signature without breakages, I guess the scoping is a nice little thing to be grateful for
I apologize, I’m having a bit of trouble understanding this paragraph… if it’s not the declaration that counts, then what is it?
Adding the same non-const widget instance to multiple places usually won’t cause any problems.
“Usually” is the problem. If it CAN create problems, best practice is don’t do it. If, instead of a Container, it’s a StreamBuilder, it will give you an exception. Other widgets also can lead to problems, such as FutureBuilder or even InheritedWidget/InheritedModel (and you never know what is deep in the tree of that widget, if it is a custom one). So, better not use them this way, to be safe (especially when you can clearly avoid it, in the example).
I apologize, I’m having a bit of trouble understanding this paragraph… if it’s not the declaration that counts, then what is it?
Declarations (new) only runs the object’s constructor. And Dart constructors are pretty useless (because they can’t write final variables). I think I never saw any class in Dart using constructors to date.
In the case of Widgets, constructor is empty, so they don’t do anything. They will only do work in the build method so, in this specific case, it doesn’t matter where it is declared (in a variable or in a child property). The “problem” is the build method.
Flutter and the related logo are trademarks of Google LLC. We are not endorsed by or affiliated with Google LLC.
Using contents of this forum for the purposes of training proprietary AI models is forbidden. Only if your AI model is free & open source, go ahead and scrape.