I'm using an AnimatedList to visualize deleting and inserting items in a list. When I delete the item on the bottom of my list, the following error is thrown: RangeError (index): Invalid value: Valid value range is empty: 0, this is the error that is thrown when I remove the item on the bottom but when there are still items above that one or RangeError (index): Invalid value: Only valid value is 0: 1 when the last item is removed. The code works when I'm removing the items on the top of the list, but fails when removing the last one. Is there a simple solution for this so I can delete all my items without a problem?

Following is a simplified version of my code:

class AnimatedListDemo extends StatefulWidget {
  @override
  _AnimatedListDemoState createState() => _AnimatedListDemoState();
}

class _AnimatedListDemoState extends State<AnimatedListDemo> {
  GlobalKey<AnimatedListState> _globalKey = new GlobalKey();
  List<int> items = [];

  Widget _listItem(BuildContext context, int index, animation) {
    return SlideTransition(
      position: Tween<Offset>(
        begin: const Offset(-1, 0),
        end: const Offset(0, 0),
      ).animate(animation),
      child: ListTile(
        title: Text("${items[index]}"),
        trailing: IconButton(
          icon: Icon(Icons.delete),
          onPressed: () {
            setState(() {
              items.removeAt(index);
              _globalKey.currentState.removeItem(index,
                  (context, animation) => _listItem(context, index, animation));
            });
          },
        ),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text("AnimatedListDemo"),
          actions: [
            IconButton(
              icon: Icon(Icons.add),
              onPressed: () {
                items.add(items.length);
                _globalKey.currentState.insertItem(items.length - 1);
              },
            )
          ],
        ),
        body: AnimatedList(
          key: _globalKey,
          initialItemCount: items.length,
          itemBuilder: (context, index, animation) =>
              _listItem(context, index, animation),
        ),
      ),
    );
  }
}


Solution 1: Stefano Amorelli

The issue is that you're trying to display items[index] in the ListTile title widget when that element has already been deleted.

A workaround could be:

title: Text(index >= items.length ? '' : items[index].toString()),

So the full example could become:

class AnimatedListDemo extends StatefulWidget {
  @override
  _AnimatedListDemoState createState() => _AnimatedListDemoState();
}

class _AnimatedListDemoState extends State<AnimatedListDemo> {
  GlobalKey<AnimatedListState> _globalKey = new GlobalKey();
  List<int> items = [];

  Widget _listItem(BuildContext context, int index, animation) {
    return SlideTransition(
      position: Tween<Offset>(
        begin: const Offset(-1, 0),
        end: const Offset(0, 0),
      ).animate(animation),
      child: ListTile(
        title: Text(index >= items.length ? '' : items[index].toString()),
        trailing: IconButton(
          icon: Icon(Icons.delete),
          onPressed: () {
            setState(() {
              items.removeAt(index);
              _globalKey.currentState.removeItem(index,
                  (context, animation) => _listItem(context, index, animation));
            });
          },
        ),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text("AnimatedListDemo"),
          actions: [
            IconButton(
              icon: Icon(Icons.add),
              onPressed: () {
                items.add(items.length);
                _globalKey.currentState.insertItem(items.length - 1);
              },
            )
          ],
        ),
        body: AnimatedList(
          key: _globalKey,
          initialItemCount: items.length,
          itemBuilder: (context, index, animation) =>
              _listItem(context, index, animation),
        ),
      ),
    );
  }
}