Search code examples
flutterdartflutter-listview

Listview index is always reset


I have a widget that returns a ListView. When an item in the ListView is selected, I show the CircularProgressIndicator on the screen while downloading the data for this item, and after the download is complete, I show the ListView again. However, after the download is complete and the CircularProgressIndicator is closed, the index of the ListView is always reset (that is, the index becomes 0). In other words, without using state management, I can't keep track of the user's position on the listview before the download, how can I do this?

Sample code is below:

class ProductsListView extends StatefulWidget {
  const ProductsListView({
    Key key,
    @required this.productsInfosList,
  }) : super(key: key);

  final List<ProductInfosModels> productsInfosList;

  @override
  State<ProductsListView> createState() => _ProductsListViewState();
}

class _ProductsListViewState extends State<ProductsListView> {
  bool flagForCircularProgressIndicator = false;

  @override
  Widget build(BuildContext context) {
    return flagForCircularProgressIndicator
        ? Center(child: CircularProgressIndicator())
        : ListView.separated(
            itemBuilder: (BuildContext context, int index) {
              return InkWell(
                onTap: () async {
                  setState(() {
                    flagForCircularProgressIndicator = true;
                  });
                  await ProductsNetworking().downloadProductDocument(
                          widget.productsInfosList[index].productId.toString());
                  setState(() {
                    flagForCircularProgressIndicator = false;
                  });
                },
                child: Padding(
                  padding: const EdgeInsets.fromLTRB(8, 25, 8, 25),
                  child: Row(
                    children: [
                      Padding(
                        padding: const EdgeInsets.only(right: 8.0),
                        child: Container(
                          width: 140,
                          child: Column(
                            crossAxisAlignment: CrossAxisAlignment.center,
                            children: [
                              Icon(FontAwesomeIcons.scaleBalanced),
                              SizedBox(height: 15),
                              Text(widget.productsInfosList[index].id),
                            ],
                          ),
                        ),
                      ),
                      Expanded(
                        child: Column(
                          crossAxisAlignment: CrossAxisAlignment.start,
                          children: [
                            Text(widget.productsInfosList[index].productName),
                            SizedBox(height: 10.0),
                            Text(widget.productsInfosList[index].productionDate),
                            SizedBox(height: 10.0),
                          ],
                        ),
                      ),
                      Container(
                        width: 60,
                        child: Icon(Icons.download))
                    ],
                  ),
                ),
              );
            },
            separatorBuilder: (BuildContext context, int index) =>
                const Divider(
              color: Colors.black54,
            ),
            itemCount: widget.productsInfosList.length,
          );
  }
}

Solution

  • I reached my goal. I can keep track of the user's position on the listview before the download, using PageStorageKey. I assign a key to my listview just like below:

    ...
    ListView.separated(
            key: PageStorageKey<String>('productsListView'),
            itemBuilder: (BuildContext context, int index) {
              return InkWell(
    ...
    

    You could read Emily Fortuna's great article about keys: Keys! What are they good for?