I'm building my first Flutter app and I have some performance issues.
I have a screen with a CustomScrollView
, to especially get a custom AppBar, with a Hero image. Next, I have some fields/filters and then I have my GridView.builder
because I can have between 25 to 400 elements in this list, and I want to build them only when the user is scrolling.
But after checking, I saw that all of my elements (400) are built immediately, and makes the app very laggy.
Can you please tell me what I've done wrong?
EDIT: You can test it via this Pastebin: Just simply copy-paste it into a new flutter project https://pastebin.com/xhd9CdUp
Basically, this is the structure of my code:
CustomScrollView
SliverAppBar
SliverPadding
SliverChildListDelegate
SearchField
SizedBox
ValueListenableBuilder // hive package
GridView.builder
CardWithMenuWidget(index)
And here is my code:
@override
Widget build(BuildContext context) {
return Scaffold(
extendBodyBehindAppBar: true,
body: SafeArea(
child: LayoutBuilder(builder: (context, constraints) {
return CustomScrollView(
slivers: [
SliverAppBar(
elevation: 0,
backgroundColor: Colors.transparent,
expandedHeight: 300,
pinned: true,
flexibleSpace: FlexibleSpaceBar(
titlePadding: EdgeInsets.symmetric(vertical: 4),
title: ConstrainedBox(
constraints:
BoxConstraints(maxWidth: constraints.maxWidth * 0.5),
child: Hero(
tag: "extension-logo-${extension.uuid}",
child: CachedImage(imageUrl: extension.logoMediumUrl!),
),
),
background: Align(
alignment: Alignment.topCenter,
child: Hero(
tag: "extension-spotlight-${extension.uuid}",
child: CachedImage(
imageUrl: extension.spotlightMediumUrl!,
fit: BoxFit.fitWidth,
height: 240,
width: double.infinity,
alignment: Alignment.topCenter,
),
),
),
),
),
SliverPadding(
padding: EdgeInsets.symmetric(horizontal: 16.0),
sliver: SliverList(
delegate: SliverChildListDelegate(
[
SearchField(
controller: this._searchController,
labelText: "Search into ${extension.name}",
cancelText: 'Cancel',
),
SizedBox(height: 32),
// Dynamic item list
ValueListenableBuilder(
valueListenable:
ExtensionBox.box.listenable(keys: [_uuid]),
builder: (context, Box<Extension> box, child) {
var cardUuidList = box.get(_uuid)!.cards?.keys;
return _buildCardListGrid(cardUuidList);
},
),
FakeBottomBarPadding(),
],
),
),
),
],
);
}),
),
);
}
Widget _buildCardListGrid(cardUuidList) {
return LoadingContainer(
isLoading: _isSyncing,
child: cardUuidList == null
? Center(
child: Text('No data.'),
)
: GridView.builder(
addAutomaticKeepAlives: true,
shrinkWrap: true,
physics: ScrollPhysics(),
itemCount: cardUuidList.length,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
mainAxisSpacing: 16.0,
crossAxisSpacing: 16.0,
childAspectRatio: CardModel.ratio,
),
itemBuilder: (context, cardIndex) {
String cardUuid = cardUuidList.elementAt(cardIndex);
return CardWithMenuWidget(
uuid: cardUuid,
);
},
),
);
}
Thank you!
My solution, based on my pastebin code: