flutter - Flutter RangeError(索引):无效值:有效值范围为空:0
问题描述
我从我的 api 获取数据之前我正在起诉硬编码的 json 数据,因此它在应用程序中完美运行,但现在当我使用 API 数据时,它显示此错误
RangeError(索引):无效值:有效值范围为空:0
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
bool showApp = false;
var _questions = new List<Questions>();
_getQuestions() {
API.getUsers().then((response) {
setState(() {
Iterable list = json.decode(response.body);
print(list);
print(list);
_questions = list.map((model) => Questions.fromJson(model)).toList();
print(_questions);
showApp = true;
});
});
}
initState() {
super.initState();
_getQuestions();
}
int index = 0;
bool shouldShow = false;
@override
Widget build(BuildContext context) {
int size = _questions.length;
void nextQuestion() {
if (index < size - 1)
setState(() {
index++;
});
print(index);
}
double percentage1Calculate() {
int wouldClick = 12;
int ratherClick = 13;
double percentage1 = wouldClick / (wouldClick + ratherClick) * 100;
return percentage1;
}
double percentage2Calculate() {
int wouldClick = 2;
int ratherClick = 3;
double percentage2 = ratherClick / (wouldClick + ratherClick) * 100;
return percentage2;
}
void percengtageTrigger(){
setState(() {
shouldShow = true;
});
Timer timer = Timer(Duration(milliseconds: 1350), () {
setState(() {
shouldShow = false;
});
});
}
final PrimaryColor = const Color(0xff404040);
final PreferredSizeWidget appBar = AppBar(
centerTitle: true,
title: Text(
'Would you Rather',
style: TextStyle(fontFamily: 'FredokaOne'),
),
backgroundColor: PrimaryColor,
);
double stackHeight = (MediaQuery.of(context).size.height -
appBar.preferredSize.height -
MediaQuery.of(context).padding.top);
double stackWidth = MediaQuery.of(context).size.width;
return Scaffold(
backgroundColor: Color(0xff404040),
appBar: appBar,
body: Stack(
children: [
GestureDetector(
onTap: () {
percengtageTrigger();
},
child: Container(
height: stackHeight * 0.5,
width: stackWidth,
color: Colors.blue,
child: Column(
children: <Widget>[
shouldShow
? Container(
padding: const EdgeInsets.only(top: 10, right: 10),
height: stackHeight * 0.1,
color: Colors.blue,
width: double.infinity,
child: Column(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
Text(
'${percentage1Calculate().toStringAsFixed(0)}%',
style: TextStyle(
color: Colors.white,
fontSize: 23,
fontFamily: 'NewsCycle',
),
),
],
))
: Container(
height: stackHeight * 0.1,
color: Colors.blue,
width: double.infinity,
),
Container(
color: Colors.blue,
height: stackHeight * 0.4,
width: double.infinity,
child: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.only(top: 20),
child: Text(
_questions[index].would, //here its showing error
style: TextStyle(
color: Colors.white,
fontSize: 23,
fontFamily: 'NewsCycle',
),
),
),
],
)),
],
),
),
),
GestureDetector(
onTap: () {
percengtageTrigger();
},
child: Align(
alignment: Alignment.bottomCenter,
child: Container(
height: stackHeight * 0.5,
width: stackWidth,
color: Colors.red,
child: Column(
children: <Widget>[
shouldShow
? Container(
padding:
const EdgeInsets.only(top: 10, right: 10),
height: stackHeight * 0.1,
color: Colors.red,
width: double.infinity,
child: Column(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
Text(
'${percentage2Calculate().toStringAsFixed(0)}%',
style: TextStyle(
color: Colors.white,
fontSize: 23,
fontFamily: 'NewsCycle',
),
),
],
))
: Container(
height: stackHeight * 0.1,
color: Colors.red,
width: double.infinity,
),
Container(
color: Colors.red,
height: stackHeight * 0.4,
width: double.infinity,
child: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.only(top: 40),
child: Text(
_questions[index].rather,
style: TextStyle(
color: Colors.white,
fontSize: 23,
fontFamily: 'NewsCycle',
),
),
),
],
)),
],
),
),
),
),
Align(
alignment: Alignment.center,
child: Container(
width: stackWidth,
height: stackHeight * 0.015,
color: Color(0xff404040),
),
),
Align(
alignment: Alignment.center,
child: Container(
width: stackWidth,
height: stackHeight * 0.15,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Color(0xff404040),
),
child: Align(
alignment: Alignment.center,
child: GestureDetector(
onTap: () {
nextQuestion();
},
child: Text(
"SKIP",
style: TextStyle(
color: Colors.white,
fontFamily: 'FredokaOne',
fontSize: 27),
),
),
)),
),
],
));
}
}
还要在显示错误的代码中注释。我不知道如何解决它,但我认为问题是因为在调用索引数据之前未加载 API 数据?
尝试使用 Futurebuild 函数,但它只是继续加载函数并显示指示器,当它在 termail 中加载时不显示容器,它继续将值打印为无限循环。
class _MyHomePageState extends State<MyHomePage> {
bool showApp = false;
var _questions = new List<Questions>();
Future<List> _getQuestions() async {
final response = await API.getUsers();
setState(() {
Iterable list = json.decode(response.body);
print(list);
print(list);
_questions = list.map((model) => Questions.fromJson(model)).toList();
print(_questions);
showApp = true;
});
return Future.value(_questions);
}
int index = 0;
bool shouldShow = false;
@override
Widget build(BuildContext context) {
int size = _questions?.length;
void nextQuestion() {
if (index < size - 1)
setState(() {
index++;
});
print(index);
}
double percentage1Calculate() {
int wouldClick = 12;
int ratherClick = 13;
double percentage1 = wouldClick / (wouldClick + ratherClick) * 100;
return percentage1;
}
double percentage2Calculate() {
int wouldClick = 2;
int ratherClick = 3;
double percentage2 = ratherClick / (wouldClick + ratherClick) * 100;
return percentage2;
}
void percengtageTrigger() {
setState(() {
shouldShow = true;
});
Timer timer = Timer(Duration(milliseconds: 1350), () {
setState(() {
shouldShow = false;
});
});
}
final PrimaryColor = const Color(0xff404040);
final PreferredSizeWidget appBar = AppBar(
centerTitle: true,
title: Text(
'Would you Rather',
style: TextStyle(fontFamily: 'FredokaOne'),
),
backgroundColor: PrimaryColor,
);
double stackHeight = (MediaQuery.of(context).size.height -
appBar.preferredSize.height -
MediaQuery.of(context).padding.top);
double stackWidth = MediaQuery.of(context).size.width;
return FutureBuilder(
initialData: null, //initial default data if you have some
future: _getQuestions(),
builder: (BuildContext context,
AsyncSnapshot<List> snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
if (snapshot.hasData) {
print("Data found, You can continue");
return Center(child: Text('Datafound'));
} else if (snapshot.hasError) {
return Center(child: Text('HaSError'));
}
} else {
print("loading");
return CircularProgressIndicator();
}
});
}
}
解决方案
问题似乎是您所怀疑的。在构建方法开始执行之前数据不可用,因此我们遇到了超出范围的错误。这个问题的解决方案是在你的构建方法中使用FutureBuilder 。
不要在 initState 中获取数据,而是将代码包装在您的构建方法中并将FutureBuilder
设置getUser()
为. 看看下面的代码片段future
FutureBuilder
@override
Widget build(BuildContext context) {
return FutureBuilder(
initialData:null //initial default data if you have some
future: API.getUsers(),
builder:(BuildContext context,AsyncSnapshot snapshot){
if(snapshot.ConnectionState==ConnectionState.none||snapshot.ConnectionState==ConnectionState.waiting){
print("data has not been fetched yet");
return CircularProgressIndicator();
}
else{
if(snapshot.hasData){
print("Data found, You can continue");
//decode your json here and initialize the variables you need
return Scaffold(
// your widgets
);
}else{
print("No data found");
return Text("No data found");
}
}
}
);
}
在你的情况下,你会做这样的事情
import 'package:flutter/material.dart';
class _MyHomePageState extends State<MyHomePage> {
bool showApp = false;
var _questions = new List<Questions>();
// Future<List> _getQuestions() async {
// final response = await API.getUsers();
// setState(() {
// Iterable list = json.decode(response.body);
// print(list);
// print(list);
// _questions = list.map((model) => Questions.fromJson(model)).toList();
// print(_questions);
// showApp = true;
// });
// return Future.value(_questions);
// }
int index = 0;
bool shouldShow = false;
@override
Widget build(BuildContext context) {
int size = _questions?.length;
void nextQuestion() {
if (index < size - 1)
setState(() {
index++;
});
print(index);
}
double percentage1Calculate() {
int wouldClick = 12;
int ratherClick = 13;
double percentage1 = wouldClick / (wouldClick + ratherClick) * 100;
return percentage1;
}
double percentage2Calculate() {
int wouldClick = 2;
int ratherClick = 3;
double percentage2 = ratherClick / (wouldClick + ratherClick) * 100;
return percentage2;
}
void percengtageTrigger() {
setState(() {
shouldShow = true;
});
Timer timer = Timer(Duration(milliseconds: 1350), () {
setState(() {
shouldShow = false;
});
});
}
final PrimaryColor = const Color(0xff404040);
final PreferredSizeWidget appBar = AppBar(
centerTitle: true,
title: Text(
'Would you Rather',
style: TextStyle(fontFamily: 'FredokaOne'),
),
backgroundColor: PrimaryColor,
);
double stackHeight = (MediaQuery.of(context).size.height -
appBar.preferredSize.height -
MediaQuery.of(context).padding.top);
double stackWidth = MediaQuery.of(context).size.width;
return FutureBuilder(
initialData: null, //initial default data if you have some
future: API.getUsers(),
builder: (BuildContext context, AsyncSnapshot<List> snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
if (snapshot.hasData) {
var response = snapshot.data;
print("Data found, You can continue");
Iterable list = json.decode(response.body);
print(list);
print(list);
_questions =
list.map((model) => Questions.fromJson(model)).toList();
print(_questions);
showApp = true;
return Center(child: Text('Datafound'));
} else if (snapshot.hasError) {
return Center(child: Text('HaSError'));
}
} else {
print("loading");
return CircularProgressIndicator();
}
});
}
}
推荐阅读
- javascript - 在网络中的多个 Firebase 项目中验证同一用户
- python - Python 3.6 上的 TensorFlow - 如何避免会话创建开销
- angular5 - ag-grid angular 5 导出隐藏,列
- sql-server - 从公共 Web 浏览器访问 SSRS
- html - 如何突出显示基于 html 的时事通讯中的特定单词?
- php - 给定 1000 个字符串的数组,每个字符串都有一个关联的时间间隔值 X,我如何每 x 分钟为每个字符串执行一项任务?
- vb.net - 项目 VB.Net 的参考文献中的错误
- java - 加载 SVG 图像 url 并更改图像颜色
- xcode - 为参数“appIdName”提供了无效值“io.ionic.starter”
- php - 使用 LOAD DATA LOCAL INFILE 在 MySQL 中的 php CSV 导入问题