Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is extending a widget really an antipattern?

I've read in couple places that extending a Flutter widget is an anti-pattern. Is that true?

I've used widget subclassing to cut down on nesting by subclassing the widget I'm removing and put its widgets in its constructor, like so

class Foo extends FormBuilder {
    Foo() : super (
        // bunch of widgets here
    );
}

Extending a stateless widget seems more popular, but it adds a few more lines of code and a widget to the tree, which isn't my preference:

class Foo extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
    return FormBuilder(
       // bunch of widgets here
    );
}

I've read returning a widget from a function is an antipattern because it breaks rendering optimization. Does my first approach likewise have hidden side effects? I.e., is it really an antipattern?

like image 877
buttonsrtoys Avatar asked Aug 20 '20 10:08

buttonsrtoys


People also ask

What is the use of expanded widget?

Expanded widget is basically a shorthand of Flexible widget. But if you are planning to build responsive apps or web apps, then you should definitely switch to Flexible to get more fit options. const Expanded ( {Key? key, int flex: 1, required Widget child} ) child: This property sets the widget tree to be placed inside the Expanded widget.

What is expanded widget in flutter?

Expanded widget is similar to the Flexible widget in flutter, with its fit property set to FlexFit.tight as default. Expanded widget is basically a shorthand of Flexible widget. But if you are planning to build responsive apps or web apps, then you should definitely switch to Flexible to get more fit options. Constructor of Expanded class:

Is it an anti-pattern to split a build function into classes?

I had a debate on here a while back with some other redditors who were saying that splitting your build function into separate functions within a class is an anti-pattern and will negatively effect the performance of your app.

Why is extraction an anti-pattern?

The "extraction" itself is not an anti-pattern. Anti-pattern is the idea that if you have, e.g., a StatefulWidget and something changes in it, the build function is triggered which means that all the "extracted" functions also re-runs.


2 Answers

Extending stateful widgets can lead to problems as their state is typed to the superclass and you can not extend their state as most state classes are kept private. A lot of the lookup methods like BuildContext.findAncestorStateOfType() will potentially fail.

Extending stateless widgets should work in most cases but is not recommended, as you have already discovered.

In general with the whole reactive and widget nature of Flutter the principal of composition over inheritance is a good pattern to follow.

You compose widgets into new widgets into new widgets into new widgets into new widgets... You get the point.

Besides that, you save 2 lines of code that mostly get auto generated but you rob yourself of all the simple helpers in VSCode/IntelliJ like "Wrap widget with padding". It is a lot harder to wrap the extended FormBuilder with a padding on all usages in your app. If you compose it is simple, just wrap it inside Foo. Same goes for all other widgets that you use for theming, colors, font styles etc. - padding is just an example.

like image 135
kuhnroyal Avatar answered Oct 08 '22 11:10

kuhnroyal


Flutter is more of composition rather than Inheritance. But Inheritance using StatelessWidget will always be useful when parent widgets need to be reused in the child.

Eg:

class FormBuilder extends StatelessWidget {
  Widget getWidget() {
    return Text('Child Text');
  }

  @override
  Widget build(BuildContext context) {
    return Text('FormBuilder Text');
  }
}

class Foo extends FormBuilder {
  Foo() : super();

  @override
  Widget build(BuildContext context) {
    return getWidget();
  }
}

So, Widget which will call Foo() Widget that Widget Element tree will be

-- Foo

-- Container

If its normal Composition then Element tree would be for this

class Foo extends StatelessWidget {
      Foo() : super();
    
      @override
      Widget build(BuildContext context) {
        return FormBuilder();
      }
    }

-- Foo

-- FormBuilder

-- Text

There is not any official doc that says its bad pattern but flutter designed by taking Composition in mind. So, personally I never observed any such performance or lagging issue with inheritance, so I would suggest Inheritance is not a bad choice to use it.

like image 2
Jitesh Mohite Avatar answered Oct 08 '22 10:10

Jitesh Mohite