AnimationList Flutter 中的 RangeError?

RangeError in AnimationList Flutter?

我正在做一个项目,我正在其中生成一个订单列表。每当我尝试从列表中删除一个项目。它抛出 RangeError (index): Invalid value: Only valid value is 0: 1 的异常。 但是,它会同时删除该项目。如果存在范围问题,为什么要删除该项目?或者这个错误是什么时候产生的?另一件事是如何在特定小部件中应用 try/catch?

代码如下:

class OrderList extends StatefulWidget {
  @override
  _OrderListState createState() => _OrderListState();
}

class _OrderListState extends State<OrderList> {
  CartList cart = CartList.instance;
  final GlobalKey<AnimatedListState> _key = GlobalKey();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Colors.red,
        elevation: 0.0,
        title: Text('Orders'),
        centerTitle: true,
        actions: <Widget>[
          Padding(
            padding: const EdgeInsets.all(16.0),
            child: Badge(
              child: Icon(Icons.shopping_cart, color: Colors.white, size: 40),
              badgeContent: Text(
                cart.listLength(),
                style: TextStyle(color: Colors.white),
              ),
              badgeColor: Colors.amber,
              toAnimate: true,
              animationType: BadgeAnimationType.fade,
            ),
          ),
        ],
      ),
      body: AnimatedList(
        key: _key,
        initialItemCount: cart.list.length,
        itemBuilder: (context, index, animation) {
          return _buildItem(cart.list[index], animation, index);
        },
      ),
    );
  }

  Widget _buildItem(FoodItem list, Animation<double> animation, int index) {

      return SizeTransition(
        sizeFactor: animation,
        child: Card(
          elevation: 2,
          child: ListTile(
            leading: CircleAvatar(
              backgroundImage: AssetImage('assets/${cart.list[index].img}'),
            ),
            title: Text(cart.list[index].name),
            subtitle: Text(
                '${cart.list[index].quantity} x ${cart.list[index].price} = ${cart.list[index].quantity * cart.list[index].price}'),
            trailing: IconButton(
              icon: Icon(
                Icons.delete,
                color: Colors.red,
              ),
              onPressed: (){
                _removeItem(index);
                setState(() {

                });
              },
            ),
          ),
        ),
      );

  }

  void _removeItem(int index) {
    FoodItem removeItem = cart.list.removeAt(index);
    AnimatedListRemovedItemBuilder builder = (context, animation){
      return _buildItem(removeItem, animation, index);
    };
    _key.currentState.removeItem(index, builder);
  }
}

您可以复制粘贴运行下面的完整代码
默认 insert/remove 动画持续时间为 Duration(milliseconds: 300)
你可以等 milliseconds: 350

onPressed: () async{
              _removeItem(index);
              await Future.delayed(Duration(milliseconds: 350), () {});
              setState(() {
                cart.list.removeAt(index);
              });
            },

完整代码

import 'package:flutter/material.dart';

class FoodItem {
  String name;
  String img;
  int quantity;
  double price;

  FoodItem({this.name, this.img, this.quantity, this.price});
}

class CartList {
  List<FoodItem> list = [
    FoodItem(
        name: "1",
        img: "https://picsum.photos/250?image=9",
        quantity: 1,
        price: 10.0),
    FoodItem(
        name: "2",
        img: "https://picsum.photos/250?image=10",
        quantity: 2,
        price: 20.0),
    FoodItem(
        name: "3",
        img: "https://picsum.photos/250?image=11",
        quantity: 3,
        price: 30.0),
    FoodItem(
        name: "4",
        img: "https://picsum.photos/250?image=12",
        quantity: 4,
        price: 40.0)
  ];
}

class OrderList extends StatefulWidget {
  @override
  _OrderListState createState() => _OrderListState();
}

class _OrderListState extends State<OrderList> {
  CartList cart = CartList();
  final GlobalKey<AnimatedListState> _key = GlobalKey();

  @override
  Widget build(BuildContext context) {
    print(cart.list.length);
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Colors.red,
        elevation: 0.0,
        title: Text('Orders'),
        centerTitle: true,
      ),
      body: cart.list.length == 0
          ? Container(child: Text("empty"))
          : AnimatedList(
              key: _key,
              initialItemCount: cart.list.length,
              itemBuilder: (context, index, animation) {
                print(index);
                return _buildItem(cart.list[index], animation, index);
              },
            ),
    );
  }

  Widget _buildItem(FoodItem list, Animation<double> animation, int index) {
    return SizeTransition(
      sizeFactor: animation,
      child: Card(
        elevation: 2,
        child: ListTile(
          leading: CircleAvatar(
            backgroundImage: NetworkImage('${cart.list[index].img}'),
          ),
          title: Text(cart.list[index].name),
          subtitle: Text(
              '${cart.list[index].quantity} x ${cart.list[index].price} = ${cart.list[index].quantity * cart.list[index].price}'),
          trailing: IconButton(
            icon: Icon(
              Icons.delete,
              color: Colors.red,
            ),
            onPressed: () async{
              _removeItem(index);
              await Future.delayed(Duration(milliseconds: 350), () {});
              setState(() {
                cart.list.removeAt(index);
              });
            },
          ),
        ),
      ),
    );
  }

  void _removeItem(int index) {
    //FoodItem removeItem = cart.list.removeAt(index);
    FoodItem removeItem = cart.list[index];
    AnimatedListRemovedItemBuilder builder = (context, animation) {
      return _buildItem(removeItem, animation, index);
    };
    _key.currentState.removeItem(index, builder);
    //cart.list.removeAt(index);
  }
}

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: OrderList(),
    );
  }
}