GridView.builder in CustomScrollView loads all items

1.6k Views Asked by At

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!

1

There are 1 best solutions below

1
On

My solution, based on my pastebin code:

CustomScrollView(
  SliverAppBar(),
  ...
  ValueListenableBuilder(
    valueListenable: _list,
    builder: (context, listBuilder, child) {
      return SliverGrid(
        gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
          crossAxisCount: 3,
          mainAxisSpacing: 16.0,
          crossAxisSpacing: 16.0,
          childAspectRatio: 635 / 889,
        ),
        delegate: SliverChildBuilderDelegate(
          (c, i) {
            return ItemWidget(listBuilder[i]);
          },
          childCount: _list.value.length,
        ),
      );
    },
  ),
)