Consider the case that I have 3 adjacent list view with each list view having a sized widget of some height. Each list view has around 24 child items. I'm trying to scale the widget using onScaleUpdate in GestureDetector.
onScaleUpdate I want to change the height of each child item of all the 3 listviews.
Is rebuilding all child better or should I rebuild the whole widget?
As #Yeasin Sheikh pointed out, using ListView.builder is good because it builds only the needed children (the ones inside the screen and just a few ones outside as precaution). And as to actually answering your question, I'm no Flutter expert, but using ListView.builder I don't think it makes that much difference, Flutter is intelligent enough to solve this by itself.
Related
I'm working on a custom calendar package but I'm having some performance difficulties while doing that.
My calendar layout is built from PageViews and each pageview contains a Gridview and each GridView contains 42 children representing the days of the month. Like this:-
Issue -
The problem is with scrolling the pageview. When I scroll to the new PageView the new PageView gets build and it builds its GridView and GridView builds its Children. All these tasks while scrolling leads to jank in scrolling animation.
Note: Scrolling to previous PageViews is smooth because I'm using AutomaticKeepAlives in PageView which stops PageView from rebuilding constantly on scroll.
DartPad -
The example DartPad for the above calendar can be found here - https://dartpad.dev/?id=762d835c5b9acadd785ee9269294c1e6
Now, what I'm looking for are the ways through which I can improve its performance.
Maybe I can somehow reuse the components for GridView children's dates by manually caching them by storing them as fields somewhere. But I don't know if that would work as these date styles have non-constant properties like the trailing one has different colors and the general one has a different one.
Maybe I can somehow preload pageviews in advance? I don't know if that would work when swiping fast.
Also, if it matters, currently I'm using Riverpod in my package for managing the calendar state.
So, if there is any way to improve the performance then please help me with that.
Current dirty solutions I found to this problem are:-
Setting viewportFraction: 0.99 in PageController of PageView. (It will help as it preloads the previous page and forward page). Suggested here #504337877.
Or use this preload_page_view package. Suggested here #636388237.
Currently, flutter doesn't support pre caching the PageView pages in advance but there are several issues about it on Github like this - #31191 , #45632 , and a closed pull request #42107 due to IOS related issue.
I failed to reuse the same widget in multiple places without rebuilding them.
And even if I succeed with the above I might fail to reuse states of child widgets of PageView as changing Pages means the whole child of PageView to be rebuilt as the index is new. So I cannot cache child widgets until I can reuse states in PageView.builder and GridView.Builder. A similar case for ListView is described in #49126.
If I'm wrong about the reusing same widget at multiple places then please correct me with a working small example as I'm more than happy to learn more. You can use this DartPad as starting point. The task is to bring the rebuild of customContainer from 42 to 1.
Not accepted as an answer as there could be more great answers to this in the future.
If we implement any chart ( whether it be a Linechart or Barchart from chart_flutter ) and in behaviours we have added charts.PanAndZoomBehavior(), pan and zoom behaviour is working fine when it is added in a screen without a scrollview
Here is the scenario Widget hierarchy as
SingleChildScrollView -> charts.LineChart
In gesture arena only SingleChildScrollView gesture is winning, Pan and zoom Behaviour is not working google/charts google/charts#677
This article is helpful https://medium.com/koahealth/combining-multiple-gesturedetectors-in-flutter-26d899d008b2
Does any one know what can be a better approach for this
I believe that is because you need to wrap the Chart Widget that is inside some other widget that has physics (property) in it.. The charts itself doesn't have any physics defined. It's managed using states model references.. I had this problem a long time ago too.. Here's my recommendation (with very amateurish knowledge on flutter):
First, I would wrap my charts within a card widget.
Second, I would avoid using SingleChildScrollView. Unless you are absolutely certain what widget you are building under that parent and they each have Intrinsic sizes defined within the child widgets. I would highly recommend using CustomScrollView -> And add a simple SliverChildBuilderDelegate. That lazily builds your charts (now wrapped in a card/container/column.. anything you chose).. That way you don't have to worry about sizes and scrolling. And any children that you add gets lazily built when they scroll into viewport..
I want to display some widgets in a Wrap, and if the widgets are too many to fit on one row, I want to display different widgets (more compact versions of the normal widgets).
How can I achieve this, without resorting to manual measurements of screen width and children? Is there any built-in way to do this with a Wrap or some other widget?
What if with the compact version, the row is still full. Do you want to display the children in multiline then or wrap them with the next line? If it's the latter, then I think it's best to use Wrap from the beginning.
Another practical way is to make the child adaptable as well, by using FittedBox or make it scrollable horizontally by using SingleChildScrollView or ListView.
There can be other scenarios when it's better to show just 4-5 children that's enough to fit a row. Then have a button allowing user to navigate to a detail screen display all the children in a grid or list.
Like the topic I was wondering of there are any circumstances one should use the regular ListView instead of the ListView.builder in flutter, like if there are few items in a list could the ListView give better performance?
ListView has actually four different ways to use it , But let discuss ListView and ListView.builder
ListView : It has a children
property that takes a collection of static widgets. A ListView takes a small number of other widgets and makes it scrollable. Why a “small number”? Because this is designed to be a static list, one that you, the developer, simply types into the build() method
by hand.
ListView.builder : ListView’s alternative constructor, ListView.builder receives two
parameters, an itemCount and an ItemBuilder property that is a
function. This makes the ListView lazy-loaded. The itemBuilder function
dynamically creates children widgets on demand. As the user scrolls close
to the bottom of the list, itemBuilder creates new items to be scrolled into
view. And when we scroll something far enough off the screen, it is paged
out of memory and disposed of. Pretty cool.
Reference : taken from Rap Payne's Beginning App Development with Flutter (Great Book for beginners! , not an affiliate link).
official documentation for ListView .
ListView is the most commonly used scrolling widget. It displays its children one after another in the scroll direction. So if you just want to show some widgets below earch other and you need to scroll them you use ListView.
ListView.builder is a way of constructing the list where children’s (Widgets) are built on demand. However, instead of returning a static widget, it calls a function which can be called multiple times (based on itemCount ) and it’s possible to return different widget at each call.
I guess the simple answer you were looking for is:
Use ListView.builder whenever you iterate over an array of 'similar' elements.
Use ListView when items in your list are completely different from one another.
Think of ListView as scrollable Column
I use GridView in my Flutter's app. Size my GridView is 30x4(with different widgets).
I need to update one widget in my gridView. I have two solutions and I need to choose the best.
Update all GridView. It is easy but I think this is not optimal (rebuild the entire grid for one change).
Update one widget. it is more complicated. but I know how to do it. This is a similar example.
what do you advise?