Flutter RangeError(索引):无效值:只有有效值为0:1

Flutter RangeError(索引):无效值:只有有效值为0:1,flutter,Flutter,我是个新手。我正在尝试将数据列表添加到视图中。数据列表具有不同长度的不同订单项集。我从API获取数据,但由于订单数据的长度不同,我得到的错误如下图所示。我的json api如下所示: 我的完整小部件代码: class OnProcessPage extends StatefulWidget { @override State<StatefulWidget> createState() { return _OnProces

我是个新手。我正在尝试将数据列表添加到视图中。数据列表具有不同长度的不同订单项集。我从API获取数据,但由于订单数据的长度不同,我得到的错误如下图所示。我的json api如下所示:

我的完整小部件代码:

    class OnProcessPage extends StatefulWidget {
         @override
         State<StatefulWidget> createState() {
          return _OnProcessTile();
        }
    }

      class _OnProcessTile extends State<OnProcessPage> {
      bool _isLoading = false;
      List<ListD> foodData = [];
      List<Orderdata> orderData = [];
      SharedPreferences sharedPreferences;

      @override
      void initState() {
        super.initState();
        setState(() {
          _isLoading = true;
        });
        getPrefs();
        getOnProcessRequest();
      }
@override
  Widget build(BuildContext context) {
    return Center(
        child: Stack(
      children: <Widget>[
        Opacity(
          opacity: _isLoading
              ? 0.3
              : 1, // You can reduce this when loading to give different effect
          child: AbsorbPointer(
            absorbing: _isLoading,
            child: _buildCardList(context),
          ),
        ),
        Opacity(
            opacity: _isLoading ? 1.0 : 0,
            child: Center(
              child: CircularProgressIndicator(
                backgroundColor: Theme.of(context).primaryColor,
              ),
            )),
      ],
    ));

  }

  Widget _buildCardList(BuildContext context) {
    return ListView.builder(
        itemCount: foodData == null ? 0 : foodData.length,
        itemBuilder: (context, int index) {
          return Wrap(
            children: <Widget>[
              Container(
                  margin: EdgeInsets.only(bottom: 10),
                  child: Card(
                      child: Column(
                    children: <Widget>[
                       _buildCardView(context, index),
                      _cardBottomView(context, index)
                    ],
                  )))
            ],
          );
        });
  }

  Widget _buildCardView(BuildContext context, int index) {
    return Wrap(
      children: <Widget>[
        Container(
          child: Container(
            margin: EdgeInsets.all(10.0),
            child: Column(
              children: <Widget>[
                _cardTopSection(context, index),
                _cardMiddleSection(context, index),
                _cardTotalPrice(context, index),
                Container(
                  height: 1,
                  color: Color.fromRGBO(232, 232, 232, 1),
                ),
              ],
            ),
          ),
        ),
      ],
    );
  }
  Widget _cardTotalPrice(BuildContext context, int i) {
    return Container(
      margin: EdgeInsets.only(bottom: 5.0),
      child: Padding(
        padding: EdgeInsets.only(top: 3, bottom: 3),
        child: Row(
          children: <Widget>[
            Expanded(
              child: Text(""),
            ),
            Expanded(
              child: Text("Total",
                  style: TextStyle(
                    fontWeight: FontWeight.bold,
                    fontSize: 18,
                  )),
            ),
            Expanded(
              child: Text(
                "${foodData[i].finalPrice}",
                style: TextStyle(
                  fontWeight: FontWeight.bold,
                  fontSize: 18,
                ),
              ),
            )
          ],
        ),
      ),
    );
  }
  Widget _cardTopSection(BuildContext context, int index) {
    return Container(
      color: Color.fromRGBO(232, 232, 232, 1),
      child: Row(
        children: <Widget>[
          _topLeftSection(index),
          _topmiddleSection(index),
          _toprightSection(index)
        ],
      ),
    );
  }

  Widget _cardMiddleSection(BuildContext context, int i) {
    return Container(
      margin: EdgeInsets.only(top: 10.0),
      child: ListView.builder(
          shrinkWrap: true,
          physics: const NeverScrollableScrollPhysics(),
          itemCount:
              foodData[i].orderdata == null ? 0 : foodData[i].orderdata.length,
          itemBuilder: (context, i) {
            print("Item Builder");
            print(i);
            print("Item Builder");
            return _cardMiddleItems(i);
          }),
    );
  }

  Widget _cardMiddleItems(int i) {
    print("Middle");
    print(i);
    print("Middle");

    return Container(
      margin: EdgeInsets.only(bottom: 5.0),
      child: Padding(
        padding: EdgeInsets.only(top: 3, bottom: 3),
        child: Row(
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          children: <Widget>[
            Expanded(
              child: Text("${orderData[i].food.name}"),
            ),
            Expanded(
              child: Text("${orderData[i].foodQty}"),
            ),
            Expanded(
              child: Text("${orderData[i].price}"),
            ),
          ],
        ),
      ),
    );
  }

  Widget _topLeftSection(int index) {
    return Container(
      child: CircleAvatar(
        backgroundImage: AssetImage('assets/images/momo.jpg'),
        backgroundColor: Colors.lightGreen,
        radius: 24.0,
      ),
    );
  }

  Widget _topmiddleSection(int i) {
    return Expanded(
      child: Container(
        child: Column(
          children: <Widget>[
            Text("Coldplay "),
            Text("${foodData[i].createdAt}")
            // new Text("Hi whatsup?"),
          ],
        ),
      ),
    );
  }

  Widget _toprightSection(int index) {
    return Expanded(
      child: Container(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.spaceAround,
          children: <Widget>[
            Text(
              "#" + "${foodData[index].id}",
              style: TextStyle(color: Colors.black, fontSize: 18.0),
            ),
          ],
        ),
      ),
    );
  }

  Widget _cardBottomView(BuildContext context, int index) {
    return Row(
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      crossAxisAlignment: CrossAxisAlignment.center,
      children: <Widget>[
        Text(
          "Order Status",
          style: TextStyle(fontSize: 18),
        ),
        RaisedButton(
          onPressed: () => {},
          color: Colors.green,
          child: Text(
            "Cooking",
            style: TextStyle(color: Colors.white),
          ),
        ),
        RaisedButton(
          onPressed: () => {
            sharedPreferences.setBool('process', true),
            sharedPreferences.setBool('new', false),
            Navigator.push(
                context,
                MaterialPageRoute(
                  builder: (BuildContext context) => RequestDetails(),
                  settings: RouteSettings(
                    arguments: foodData[index],
                  ),
                ))
          },
          color: Theme.of(context).primaryColor,
          child: Text("Details", style: TextStyle(color: Colors.white)),
        ),
      ],
    );
  }

  Future<NewRequestResponse> getOnProcessRequest() async {
    print("OnProcess");
    SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
    String token = sharedPreferences.getString("api_token");
    Map<String, String> headers = {"Authorization": token};
    var jsonResponse;
    NewRequestResponse newRequestResponse;
    var response = await http.post(
        "url",
        headers: headers);
    if (response.statusCode == 200) {
      print("Onprocess Inside 200");
      jsonResponse = json.decode(response.body);
      print(jsonResponse);
      if (jsonResponse != null) {
        newRequestResponse = new NewRequestResponse.fromJson(jsonResponse);
        print(newRequestResponse);

        setState(() {
          foodData = newRequestResponse.data.list;
          for (int i = 0; i < foodData.length; i++) {
            orderData = foodData[i].orderdata;
          }
        });
        setState(() {
          _isLoading = false;
        });
        return newRequestResponse;
      } else {
        setState(() {
          _isLoading = false;
        });
        return null;
      }
    } else {
      setState(() {
        _isLoading = false;
      });
      jsonResponse = json.decode(response.body.toString());
      newRequestResponse = new NewRequestResponse.fromJson(jsonResponse);
      print("onProcessRequest outside 200");
      return newRequestResponse;
    }
  }

  void getPrefs() async {
    sharedPreferences = await SharedPreferences.getInstance();
  }
}

这有点棘手,所以我希望我能理解这个bug,但对我来说,问题似乎出在您的getOnProcessRequest这行:

for (int i = 0; i < foodData.length; i++) {         
        orderData = foodData[i].orderdata;
      }
在foodData的每个周期更新和覆盖orderData。我认为这样做是不对的

据我所知,应该发生的是 对于每个foodData,获取orderData的列表。 但是foodData是一个列表,orderData也是。我认为,您应该链接这些项目,这样对于每个foodData,您就可以访问它自己的orderData列表

编辑: 我不能提供一个完整的解决方案,因为这会让我太过诚实。 但我举了一个例子

final Map<String, dynamic> myApi = {
  "list": [
    {
      "id": 1,
      "orderdata": [
        {"title": "food1"},
        {"title": "food2"}
      ]
    },
    {
      "id": 2,
      "orderdata": [
        {"title": "food3"},
        {"title": "food4"}
      ]
    },
  ]
};

class OrderData {
  final String title;
  OrderData(this.title);

  @override
  String toString() {
    return title;
  }
}

class FoodData {
  final int id;
  final List<OrderData> orderData;
  FoodData(this.id, this.orderData);
}

void main() {
  final tmpMap = (myApi['list'] as List<Map<String, Object>>);
  print(tmpMap);
  List<FoodData> myList = tmpMap.map<FoodData>((elem) {
    final value = elem;
    final _id = value['id'] as int;
    final List<OrderData> _orderData =
        (value['orderdata'] as List<Map<String, String>>)
            .map<OrderData>((order) => OrderData(order['title']))
            .toList();
    return FoodData(_id, _orderData);
  }).toList();

  print(myList.length);
  for (int i = 0; i < myList.length; i++) {
    for (int j = 0; j < myList[i].orderData.length; j++) {
      print("i: $i, j: $j, elem: ${myList[i].orderData[j]}");
    }
  }
}
最后,您需要使用一个列表来更改getOnProcessRequest,因此删除orderdata,只使用fooddata,现在fooddata将为每个元素提供一个内部的订单表示

要实例化ListView.builder时:

对于第一个外部列表视图,您将使用fooddata.length 对于第二个内部ListView,您将使用foodata[i].orders.length
希望这能帮助您找到正确的解决方案这有点棘手,所以我希望我能理解这个bug,但对我来说,问题似乎出在您的getOnProcessRequest上,在这行:

for (int i = 0; i < foodData.length; i++) {         
        orderData = foodData[i].orderdata;
      }
在foodData的每个周期更新和覆盖orderData。我认为这样做是不对的

据我所知,应该发生的是 对于每个foodData,获取orderData的列表。 但是foodData是一个列表,orderData也是。我认为,您应该链接这些项目,这样对于每个foodData,您就可以访问它自己的orderData列表

编辑: 我不能提供一个完整的解决方案,因为这会让我太过诚实。 但我举了一个例子

final Map<String, dynamic> myApi = {
  "list": [
    {
      "id": 1,
      "orderdata": [
        {"title": "food1"},
        {"title": "food2"}
      ]
    },
    {
      "id": 2,
      "orderdata": [
        {"title": "food3"},
        {"title": "food4"}
      ]
    },
  ]
};

class OrderData {
  final String title;
  OrderData(this.title);

  @override
  String toString() {
    return title;
  }
}

class FoodData {
  final int id;
  final List<OrderData> orderData;
  FoodData(this.id, this.orderData);
}

void main() {
  final tmpMap = (myApi['list'] as List<Map<String, Object>>);
  print(tmpMap);
  List<FoodData> myList = tmpMap.map<FoodData>((elem) {
    final value = elem;
    final _id = value['id'] as int;
    final List<OrderData> _orderData =
        (value['orderdata'] as List<Map<String, String>>)
            .map<OrderData>((order) => OrderData(order['title']))
            .toList();
    return FoodData(_id, _orderData);
  }).toList();

  print(myList.length);
  for (int i = 0; i < myList.length; i++) {
    for (int j = 0; j < myList[i].orderData.length; j++) {
      print("i: $i, j: $j, elem: ${myList[i].orderData[j]}");
    }
  }
}
最后,您需要使用一个列表来更改getOnProcessRequest,因此删除orderdata,只使用fooddata,现在fooddata将为每个元素提供一个内部的订单表示

要实例化ListView.builder时:

对于第一个外部列表视图,您将使用fooddata.length 对于第二个内部ListView,您将使用foodata[i].orders.length
希望这将有助于您找到正确的解决方案

如果您能指出代码中发生此异常的位置,这将非常有用。您可以检查控制台上的异常堆栈跟踪。在将api的orderdata设置为来自不同长度的cardMiddleItems的列表中的_cardMiddleItems时发生异常大量的数据。我得到的订单数据长度仅为1,但在某些情况下api中有不止1个数据。如果您可以指向代码中发生此异常的位置,这将非常有用。您可以在控制台上检查异常堆栈跟踪。当将api的orderdata设置为来自_cardMiddleItems的列表中的_cardMiddleItems时,会出现异常由不同长度的数据组成。我得到的订单数据长度仅为1,但api中有不止1个数据,我能解决这个问题吗?请帮助..尝试了我所有的方法,所以我在这里问了这个问题好的,让我问你,getOnProcessRequest函数在哪里?在小部件中?或者在一个提供者中?在InitState内部,您可以在一些dartPad或任何nopaste站点中发布完整的小部件代码吗?因为现在很难确定如何帮助:/@Nbn我已经编辑了我的答案。请将我的代码复制到dartpad中,并分析我所做的工作。如果您有任何疑问,我将帮助您:我如何解决这个问题?请帮助..尝试了我所有的方法,所以我在这里问了这个问题好的,让我问你,getOnProcessRequest函数在哪里?在小部件中?或者在一个提供者中?在InitState内部,您可以在一些dartPad或任何nopaste站点中发布完整的小部件代码吗?因为现在很难确定如何帮助:/@Nbn我已经编辑了我的答案。请将我的代码复制到dartpad中,并分析我所做的工作。如果您有任何疑问,我将在此帮助您: