I have a strong background with Android development and I'm now trying to develop my first app with Flutter.
It is a common knowledge in the Android community that it's bad have too many nested views. It's bad for performance. (That's one of the reason why ConstraintLayout exists)
However, in Flutter tutorials I see that people nest a lot of widgets.
Could somebody confirm that it's not a problem to nest widgets with Flutter? Will my app suffer of bad performance if I do it?
Thanks in advance
TL;DR: Deeply nesting single-purpose widgets in Flutter is recommended.
There are fundamental differences in how Android and Flutter render view elements (aka widgets or views).
In Android, there are relatively few, complex views that inherit each other.
Each and every view provides a huge API surface, including stuff like padding, margin, colors etc.
Flutter, on the other hand, favors composition over inheritance.
Most widgets exist for a single purpose only and are very lightweight.
That means you need to nest widgets more deeply to achieve the same effects, but because their layout and rendering logic is easier, the rendering is typically faster.
For example, there's a Padding widget that makes some space around its child.
The Padding widget's rules are very simple, making the rendering very fast.
Additionally, the rules of every other widget also get simpler because they don't need to worry about padding anymore.
Basically, nesting widgets deeply is recommended in Flutter.
It's quite the opposite to Android's model:
If there's not much nesting, you probably did something wrong, because you have a huge widget that can often be split into simpler, faster, smaller widgets.
Here's an interesting Google Tech Talk about Flutter's rendering pipeline, which I recommend to anyone interested in this topic.
Nesting widgets is not a problem and is actually recommended.
In fact, the default counter application contains no less than 150 widgets.
Widgets are lightweight objects optimized specifically to create and destroy tons of them every frame. This is further prooved by Flutter FAQ:
Rather than having each widget provide a large number of parameters, Flutter embraces composition. Widgets are built out of smaller widgets that you can reuse and combine in novel ways to make custom widgets. For example, rather than subclassing a generic button widget, RaisedButton combines a Material widget with a GestureDetector widget. The Material widget provides the visual design and the GestureDetector widget provides the interaction design.
This quote says that you should purposefully nest widgets.
Related
I am working on building a mobile application using flutter and am stuck on building a resposive login screen layout. To be precise, I am using the MediaQuery to find the screen size and to find the safe area and based on that I am spacing and building containers based on percentage of screen height. I would like to know if this is the best way or if I am unnecessarily complicating the entire process. I did come across a few youtube videos where most of them give random numbers but when I try doing that, my layout most often than not ends of overflowing!
So far, I have mostly done this with just mathematical calculations. i.e. I have stuck to calculating the available height (total height - safe area) and then built all my containers based on this height (including their spacing). But, I am struggling with getting the right font size and this constant struggle to balance the UI in both android and iOS setup is eating up most of my time.
I built hundreds of screens in Flutter. It is very rare that you need to use exact screen height for a layout. Most screens fall into one of the three categories:
There are too many elements to fit into a screen of any size.
In this case you wrap your layout in SingleChildScrollView widget that has a Column child, and then put all other widgets in that Column. Users scroll down to see all visible elements they need to see.
There are too many elements to fit into smaller screen sizes, but they fit into larger screens.
In this case you still wrap your layout in SingleChildScrollView widget. Then you make your layout look nice on larger screens, but users on smaller screens still have to scroll down. This is not ideal, but sometimes it's the right solution. Making design elements smaller on a small screen often makes it hard to use or even totally unusable. Plus, having various calculations related to a screen size in your layout logic makes it a nightmare to test your app: you have to test it on all sorts of screen sizes.
All design elements can fit into a small screen.
In this case you should use Flex widgets (like Column, Row, Spacer, Center, etc.) to create your layout. These widgets already have a logic for spacing their children in the available space (for example, using mainAxisAlignment and crossAxisAlignment properties in Column and Row).
There are also widgets that can take a specified percentage of a screen (or their parent widget), but I never use them. I can imagine situations where these widgets can be useful, but for the vast majority of designs using Flex layout is a better option that results in better looking screens.
If you post your design and the layout you came up with, we can point if there are ways to optimize it.
I am learning and playing around with Flutter. Currently I am trying to reproduce an app I previously made with C# and WPF. In my Flutter app I have a list of Widgets extending CustomPainter. Now I am able to move/drag any of these widgets around the screen. What I see is that always when dragging one of this widgets all CustomPaint widgets are repainted. I checked what would happen if I decide to resize my window, and you can guess, all CustomPaint widgets are repainted.
I decided to create three different projects. One is using statefull widgets and setState to manage the state. The other is using Provider and the last one is using Riverpod. Still all Widgets extending CustomPainter are repainted when dragging a single Widget or resizing the window.
Now my question is, am I doing something wrong in my state management or is this behavior by default?
Also my C#/WPF app uses half the cpu the Flutter app uses when dragging one shape around. I did not expect such a difference. For now I did not make any complex CustomPaint obecjt in my flutter app. But should I expect a big performance reduction if I have many complex CustomPaint widgets?
am I doing something wrong in my state management or is this behavior
by default?
Yes and no. Widgets are rebuilt when the screen size changes, but dragging a widget should not make other widgets rebuild. You can try RepaintBoundary (https://api.flutter.dev/flutter/widgets/RepaintBoundary-class.html)
Should I expect a big performance reduction if I have many complex
CustomPaint widgets?
This has a lot to do with what kind of CustomPaint widgets you will be using and what is "many". You can test how long the CustomPaint widget's paint method takes, for example by using the profiler (https://docs.flutter.dev/perf/ui-performance). My assumption is that the efficiency decreases linearly as you add more CustomPaint widgets
I would like to make my Flutter app more responsive.
One simple fix would be to lay out items in a grid on larger screens, with a single-column view used on mobile screens.
What's the best way to achieve this?
Ideally, I'd like to use a GridView with a responsive number of columns, for both smaller and larger screens. This would be the most elegant solution in terms of code cleanliness. However, I'm concerned that using a single-column GridView on mobile might be less performant than using a ListView.
Does anyone here have data about potential performance penalties of this approach? Or does single-column GridView use the exact same code as ListView?
The other approach would be to use ListView vs GridView depending on the size of the window. This would lead to code duplication, but could possibly be more efficient.
I am building calendar based app and trying Flutter.
Can you give advice/example of hierarchy how build complex and efficient layout like Google Calendar daily view?
Main question: how should I layout constant hours background and overlapping dynamic events layer?
I used RecyclerView and custom RecyclerView.LayoutManager before, but have no idea about Flutter way.
You can construct your layout efficiently using GridView.custom.
A custom SliverGridDelegate can produce an aribtrary 2D arrangement of children, including arrangements that are unaligned or overlapping.
An easier option might be to use a CustomMultiChildLayout but that will require laying out all the children instead of just the ones that are visible. It could be slower, but maybe that isn't the bottleneck for a calendar app.
Suppose we've the following structure of widgets / panels in a GWT application -
A Tree menu in the left of the DockLayoutPanel which is used for navigation to different applications.
A panel in the center of the DockLayoutPanel and different content widgets getting loaded in this panel (this is controlled by the navigation tree menu.
These content widgets are composites containing one or more widgets.
One way to deal with such application is to keep singletons for all widgets / panels, which means composites will hold singletons to all of their child widgets. But I feel this is excess usage of singleton. The other alternative is to construct new Widget object every time one is needed, but this must be expensive.
What are the best practices around this? Are there any standard patterns which take care of this problem?
The other alternative is to construct new Widget object every time one is needed, but this must be expensive.
You'd be surprised. While Widget creation isn't free, in most cases, it is pretty cheap, even in DevMode. There are several widgets that are expensive to create in DevMode (specifically, the FlexTable/Grid), but those speed up drastically once you compile the application.
There doesn't seem to be any pattern specifically for this, nor can I point to any one guru giving a best practice, but in our application we had previously treated all of our top level widgets as singletons and it caused a load of issues for us. (Managing state between different screens, handling event bus events, stale data on the screen when not cleared)
We just refactored most of the code to be created on demand more (and subsequently destroyed when no longer needed) and we gained simpler code and a faster startup time.
In the end, if you do create widgets on demand, there may be a few cases where you need to increase performance by making those widgets singletons, but I think you'll find that only a few would warrant that effort.
All in all, don't assume something will be slow if you haven't tried it, and don't preemptively optimize your code.