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