2

It is quite often to see people passing a widget class or call a function which return a widget to Body property of a widget.

What confuse me is that both are actually work. But I dont understand the reason behind when to choose which to implement

For example,

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        **body: _buildContents(context),**
      ),
    );
  }
}

vs

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        **body: HomePage(),**
      ),
    );
  }
}
  • There is no difference between these method. Both are same. First one is you're using directly class and with second one you're only splitting widgets into methods. Which is consider as a best practice. With splitting method your code looks clean and readable. – Hemal Moradiya Jun 09 '21 at 08:34
  • The first case does not pass a function. It *calls* a function and passes its return value. – jamesdlin Jun 09 '21 at 08:45
  • What make me suspect is when I pass a widget class instead of a method, I would also need to provide a build method of that class. Will this make a impact on the process of rendering? Like if I update homePage() only at some point, it will only rendering the home page part? While with providing _buildContents(context) , it will render everything instead when upper widget makes a change @Hemal –  Jun 09 '21 at 08:47
  • 1
    If you want to avoid re-rendering of any widget then instead of splitting widgets into method you have to create a separate class of that perticualr widget and extend this with StatelessWidget. StatelessWidget will avoid rebuilding all the widgets repetitively. Please refer this article, you will get idea what I mean to say https://blog.codemagic.io/how-to-improve-the-performance-of-your-flutter-app./ – Hemal Moradiya Jun 09 '21 at 08:54
  • @Hemal Thanks for the article, I have read through it and it is quite useful for explaining how rebuilding work behind. To aviod making unnessary rebuild, it also mention we can achieve it by implementing SOME STATE MANAGEMENT like BlOC , provider... May I know if you know any good article explaining these well too coz I have studied a bit bloc and provider for a while, but always still find it confusing. –  Jun 09 '21 at 09:47
  • There is lots of article of BLoC pattern available but all are follwing their own method so it's hard for beginner to understand which way we have to choose. As per my knowledge you've to start with [RxDart](https://pub.dev/packages/rxdart). And you can also find some video tutorial in YouTube as well. You can also start with [flutter_bloc](https://pub.dev/packages/flutter_bloc). – Hemal Moradiya Jun 09 '21 at 10:03
  • @Hemal Exactly, there are many articles of bloc available, but it is hardly to find a good one for beginner to get a sense of it. –  Jun 10 '21 at 02:42
  • @Hemal if possible, could you point me some good article about state? I knew that when state widget is being rebuilded, the state of it is not being rebuilded. What confused me is that why state widget variable can be avoid to be deleted but stateless widget variable would be deleted after set state. Hows the mechanism behind? –  Jun 10 '21 at 06:48

2 Answers2

2

The main difference between these two is that you could use const with Widget constructors, but you cannot add const to a function call. E.g.:

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        body: _buildContents(context), // you cannot add const here
      ),
    );
  }
}

vs

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        body: const HomePage(), // If available, you can add const here
      ),
    );
  }
}

That is important for performance. When rebuilding the Widget tree, Widgets with const constructors won't rebuild - they are constants, right? However, with function calls you cannot ensure that - function body would be executed every single time on rebuild.

You could imagine that being a huge problem when this specific Widget is quite expensive to build and you are running your app, let's say, 60 fps - your "expensive" function would be called 60 times per second, which could lead to UI rendering janks in some cases.

The rule of thumb: use Widgets with const constructors wherever you can.

mkobuolys
  • 4,499
  • 1
  • 11
  • 27
  • May I know how Widget tree building work behind? if I rerender the page, what I see is the whole page is rebuilt. But what is actually really rebuild behind when we set state again. @mkobuolys –  Jun 09 '21 at 08:53
  • 1
    Well, Widgets rendering is a huge topic, you can check the resources online about "Flutter widgets rendering". Also, this SO answers provides some good details about that: https://stackoverflow.com/questions/53492705/does-using-const-in-the-widget-tree-improve-performance/62825321#62825321 – mkobuolys Jun 09 '21 at 09:39
  • You could use `const` inside function either. >Widgets with const constructors won't rebuild. It's not true. No new widget instances would be created, but the widget can be rebuild many times, there is no connection btw how widget is created and how often it would be rebuild during lifetime. – ChessMax Jun 10 '21 at 06:13
  • @mkobuolys if possible, could you point me some good article about state? I knew that when state widget is being rebuilded, the state of it is not being rebuilded. What confused me is that why state widget variable can be avoid to be deleted but stateless widget variable would be deleted after set state. Hows the mechanism behind? –  Jun 10 '21 at 06:50
  • @ChessMax you could use const inside a function, but the fact is that function would be called anyway and would return a new instance of a widget, const loses its purpose this way. About the rebuild, I am not sure if your point is valid. Simply, add a breakpoint inside any const widget's build method and make sure that the parent widget is rebuilt. You will notice that this breakpoint won't be hit, meaning the build() function is not called on the const widget, no rebuild is needed. – mkobuolys Jun 10 '21 at 07:33
  • >and would return a new instance of a widget No, you can `return const MyWidget()`, or `return _mySavedWidget;` No new widget will be created in that case. – ChessMax Jun 10 '21 at 07:40
  • @ChessMax Oh, you have this mind. Yes, that's true. – mkobuolys Jun 10 '21 at 10:13
0

a widget class

It's not a widget class, it's a widget constructor.

call a function

here it's insert not a function call, but a result of a function call.

There are plenty of reasons why to use build functions instead of a widget constructor. Some of them:

  • to make code readable and clean. If you have a huge widget tree it's difficult to find some widgets, you need to spend some time to find exact place of a widget you are looking for. It's easy to understand what widget it is, because now it has a name. And so on. Also, when a widget tree is complex it's very difficult to read it and deal with it;
  • sometimes widgets can be used several times (sometimes they are slightly differ) in the widget tree, so instead of copy all the code, we can just refer to a pre-setuped widget throw widget build function. Let's imagine, that in such a case we need to change something in our "twin" widgets. If we have a build widget function we can do it only in one place, otherwise we are to look over the code and make changes in several places;
  • sometimes what widget to use depends on some logic. It's a good idea to isolate this somewhere in the function instead of placing this logic inside the widget tree, otherwise it's complicating the code and widget tree, making difficulties to work with;
  • ...
ChessMax
  • 2,125
  • 1
  • 16
  • 16