25

I want to keepAlive my widgets which are already rendered in ListView. I was tried with addAutomaticKeepAlives:true properties which provide by ListView class.

Here is my sample code which I was used. Same issue in SliverChildBuilderDelegate delegate which provide by SliverList.

ListView.builder(
    itemBuilder: (context,index){
      return Card(
        child: Container(
          child: Image.asset("images/${index+1}.jpg",fit: BoxFit.cover,),
          height: 250.0,
        ),
      );
    },
    addAutomaticKeepAlives: true,
    itemCount:40 ,
);
Rémi Rousselet
  • 256,336
  • 79
  • 519
  • 432
NIRAV PATEL
  • 1,191
  • 2
  • 10
  • 14

4 Answers4

45

For automaticKeepAlive to work, each item that needs to be kept alive must send a specific notification.

A typical way to fire such notification is using AutomaticKeepAliveClientMixin

class Foo extends StatefulWidget {
  @override
  FooState createState() {
    return new FooState();
  }
}

class FooState extends State<Foo> with AutomaticKeepAliveClientMixin {
  @override
  Widget build(BuildContext context) {
    return Container(

    );
  }

  @override
  bool get wantKeepAlive => true;
}
Shirish Kadam
  • 689
  • 1
  • 9
  • 21
Rémi Rousselet
  • 256,336
  • 79
  • 519
  • 432
  • 3
    Is this working for image ? i tried but images still re-render when i am scrolling. If scroll slowly that time there is no issue. but In fast scrolling image widget re-render. – NIRAV PATEL Sep 28 '18 at 16:16
  • 1
    Hi can you help at all? I'm facing a similar issue with CustomScrollView and SliverList... I have a WebView that keeps reloading when the page scrolls... I have cacheExtent high enough on my CustomScrollView. I also have all the prerequisites such as: ```super.build(context);``` and the ```bool get wantKeepAlive``` override... I also have the ```AutomaticKeepAliveClientMixin``` set... Not sure what's going on, but the WebView definitely doesn't reload in something like a SingleChildScrollView.. SO I'm guessing it's the CustomScrollView/SliverList that's destroying it.. – Chris Feb 20 '20 at 17:19
  • thanks for this, even having read: https://api.flutter.dev/flutter/widgets/ListView-class.html I didn't realized that was mentioned in the last point! – Sebastian May 19 '23 at 17:25
23

As stated by AutomaticKeepAliveClientMixin and Remi's answer,

Subclasses must implement wantKeepAlive, and their build methods must call super.build (the return value will always return null, and should be ignored).

Therefore, change your build method to:

class Foo extends StatefulWidget {
  @override
  FooState createState() {
    return new FooState();
  }
}

class FooState extends State<Foo> with AutomaticKeepAliveClientMixin {
  @override
  Widget build(BuildContext context) {
    super.build(context);
    return Container(

    );
  }

  @override
  bool get wantKeepAlive => true;
}
Siddanth
  • 290
  • 3
  • 9
10

You can try looking at the cacheExtent property on listview builder as well. Setting that to a value to cover your items will keep them all alive. Thanks to Remi above. I had no idea the items needed keepAlive when using it on the list - that was not in the flutter doco previously...

Jason Scott
  • 643
  • 4
  • 15
6

if you want to keep alive a list of slivers (for CustomScrollView) all you need to do is use the 'SliverChildListDelegate' instead of 'SliverChildBuilderDelegate'

Here's my code:

final List<Product> products;
return CustomScrollView(
  controller: _scrollController,
    slivers: [
      _mySliverAppBar(context, title),
      SliverList(
        delegate: SliverChildListDelegate(
          List.generate(products.length, (index) => _myProductCard(context,products[index]))
        )
        // SliverChildBuilderDelegate(
        //   (context, index) => _myProductCard(context, products[index]),
        //   childCount: products.length,
        // ),
      ),
   ],
);

As you can see in the code, I was using SliverChildBuilderDelegate before