how to keep the state of my widgets after scrolling?

ListView.builder & GridView.builder makes items on demand. That means ,they construct item widgets & destroy them when they going beyond more than cacheExtent.

So you cannot keep any ephemeral state inside that item widgets.(So most of time item widgets are Stateless, but when you need to use keepAlive you use Stateful item widgets.

In this case you have to keep your state in a parent widget.So i think the best option you can use is State management approach for this. (like provider package, or scoped model).

Below link has similar Example i see in flutter.dev

Link for Example

Hope this answer will help for you

enter image description here


You have to store the state (favorite or not) in a parent widget. The ListView.builder widget creates and destroys items on demand, and the state is discarded when the item is destroyed. That means the list items should always be stateless widgets.

Here is an example with interactivity:

example app

class Item {
  Item({this.name, this.isFavorite});

  String name;
  bool isFavorite;
}

class MyList extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => MyListState();
}

class MyListState extends State<MyList> {
  List<Item> items;

  @override
  void initState() {
    super.initState();

    // Generate example items
    items = List<Item>();
    for (int i = 0; i < 100; i++) {
      items.add(Item(
        name: 'Item $i',
        isFavorite: false,
      ));
    }
  }

  @override
  Widget build(BuildContext context) {
    return ListView.builder(
      itemCount: items.length,
      itemBuilder: (context, index) {
        return ListItem(
          items[index],
          () => onFavoritePressed(index),
        );
      },
    );
  }

  onFavoritePressed(int index) {
    final item = items[index];
    setState(() {
      item.isFavorite = !item.isFavorite;
    });
  }
}

class ListItem extends StatelessWidget {
  ListItem(this.item, this.onFavoritePressed);

  final Item item;
  final VoidCallback onFavoritePressed;

  @override
  Widget build(BuildContext context) {
    return ListTile(
      title: Text(item.name),
      leading: IconButton(
        icon: Icon(item.isFavorite ? Icons.favorite : Icons.favorite_border),
        onPressed: onFavoritePressed,
      ),
    );
  }
}

Other answer are better for your case but this an alternative and can be used if you want to only keep several elements alive during a scroll. In this case you can use AutomaticKeepAliveClientMixin with keepAlive.

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

class FooState extends State<Foo> with AutomaticKeepAliveClientMixin {
  bool shouldBeKeptAlive = false;
  @override
  Widget build(BuildContext context) {
    super.build(context);

    shouldBeKeptAlive = someCondition();
    return Container(

    );
  }

  @override
  bool get wantKeepAlive => shouldBeKeptAlive;
}

If you don't have many items in the ListView you can replace it with a SingleChildScrollview and a Column so that the Widgets aren't recycled. But it sounds like you should have a list of items where each item has an isFavourite property, and control the icon based on that property. Don't forget to setState when toggling the favorite.