我从 API 获取数据并将其添加到数据表中,它工作正常,当我从下拉列表中选择月份时,我的数据表会根据从下拉列表中选择的月份进行修改,但最初它会打印此错误。
当我从下拉菜单中选择月份时它的变化
这里是代码
class MyAttendance extends StatefulWidget {
@override
_MyAttendanceState createState() => _MyAttendanceState();
}
class _MyAttendanceState extends State<MyAttendance> {
//List<History> _historyList;
List<History> historyList=[];
String _selectedLeave;
int monthIndex;
int month;
var monthsList=<String>[
'January',
'Febuary',
'March',
'April',
'May',
'June',
'July',
'Augest',
'September',
'October',
'November',
'December'
];
String getdate="";
void _getDate() {
final String formattedDateTime =
DateFormat('MM').format(DateTime.now()).toString();
setState(() {
getdate = formattedDateTime;
print("date "+getdate);
});
}
_userDetails() async{
SharedPreferences myPrefs=await SharedPreferences.getInstance();
setState(() {
getname=myPrefs.getString('name');
});
}
void initState() {
_userDetails();
_getDate();
_getRecord();
}
Future<List<History>> _getRecord() async{
Dio dio=new Dio();
var data={
'username':getname,
'month':month
};
return dio
.post(localhostUrlAttendanceHistory,data: json.encode(data))
.then((onResponse) async {
var jsonData=onResponse.data['data'];
//List<History> historyList = [];
for (var h in jsonData) {
History history = History(
h["Date"],
h["TimeIn"],
h["TimeOut"],
);
historyList.add(history);
}
return historyList;
})
.catchError((onerror){
print(onerror.toString());
});
}
Widget attendanceHistory(List<History>
historyList)=>
DataTable(columns: <DataColumn>[
DataColumn(label: Text("Date"),),
DataColumn(label: Text("Time in" ),),
DataColumn(label: Text("Time out")
)],
rows:
historyList
?.map((element)=>DataRow(
cells: <DataCell>[
DataCell(Text(element?.date)),
DataCell(Text(element?.timeIn)),
DataCell(Text(element?.timeOut)),
]) )?.toList());
TextEditingController fromDate=new TextEditingController();
TextEditingController toDate=new TextEditingController();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: new MyAppBar(title: Text("My Attendance"),onpressed: (){
Navigator.push(context, MaterialPageRoute(builder: (context)=>Profile()));
}),
drawer:Emp_DrawerCode(),
body:Stack(children: <Widget>[
Container(
padding: EdgeInsets.fromLTRB(25, 15, 0, 0),
child: Text("Attendance history",style: TextStyle(fontSize: 30,color: Colors.blue[900],fontWeight: FontWeight.bold),),
),
Container(
padding: EdgeInsets.fromLTRB(45, 80, 10, 0),
child:
DropdownButton<String>(
value: _selectedLeave==null?null:monthsList[monthIndex],
items:
monthsList
.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value)
);
}).toList(),
hint:Text(
"Please choose a month",
),
onChanged: (String value) {
setState(() {
_selectedLeave=value;
monthIndex = monthsList.indexOf(value);
month=monthIndex+1;
print(month);
print(_selectedLeave);
});
},
),
),
Container(
padding: EdgeInsets.fromLTRB(15, 150, 0, 0),
child:SingleChildScrollView(
scrollDirection: Axis.vertical,
child: FutureBuilder(
future: _getRecord(),
builder: (BuildContext context, AsyncSnapshot<List<History>> snapshot) {
// Check if the data has been received.
if (snapshot.hasData) {
// Return the widget and provide the received data.
return attendanceHistory(snapshot.data);
}
return Center(child: CircularProgressIndicator(),);
// print("data");
// print(snapshot.data);
// Text("No data is shown");
//return attendanceHistory(snapshot.data);
}
),
),)
]));
}
}
class History {
final String date;
final String timeIn;
final String timeOut;
History(this.date, this.timeIn, this.timeOut);
}
错误
════════ Exception caught by widgets library ═══════════════════════════════════
A non-null String must be provided to a Text widget.
'package:flutter/src/widgets/text.dart':
Failed assertion: line 378 pos 10: 'data != null'
The relevant error-causing widget was
FutureBuilder<List<History>>
lib\My_Attendance\MyAttendance.dart:171
更新: 几秒钟的红屏错误后,它显示了这个,我也没有从下拉列表中选择月份。
它现在发送这个错误
════════ Exception caught by widgets library ═══════════════════════════════════
The method 'map' was called on null.
Receiver: null
Tried calling: map<DataRow>(Closure: (History) => DataRow)
The relevant error-causing widget was
FutureBuilder<List<History>>
更新
更新:
builder: (BuildContext context, AsyncSnapshot<List<History>> snapshot) {
// Check if the data has been received.
if(snapshot.connectionState==ConnectionState.done){
if (snapshot.hasData) {
return Center(
child: Text('${snapshot.error} occured',
style: TextStyle(fontSize: 18)),
);
}
else if(snapshot.hasData){
return attendanceHistory(snapshot.data);
}
// Return the widget and provide the received data.
//return Center(child: CircularProgressIndicator(),);
}
//return attendanceHistory(snapshot.data);
return Center(child: CircularProgressIndicator(),);
// print("data");
// print(snapshot.data);
// Text("No data is shown");
}
),
请帮助我如何解决它?
答案 0 :(得分:1)
更好的做法是在从 API 获取数据时使用加载器。由于未来的构建器有一个属性来检查是否有来自 API 的响应。要检查这个只需使用
`FutureBuilder(
future: _getRecord(),
builder: (BuildContext context,
AsyncSnapshot<List<History>> snapshot) {
// Below line will check whether future has data or not
if (snapshot.connectionState == ConnectionState.done) {
// If we got an error
if (snapshot.hasError) {
return Center(
child: Text(
'${snapshot.error} occured',
style: TextStyle(fontSize: 18),
),
);
// if we got our data
} else if (snapshot.hasData) {**strong text**
if (snapshot.hasData) {
return attendanceHistory(snapshot.data);
}
return Center(child: CircularProgressIndicator(),);
}`
否则您可以使用空感知运算符来处理空值,如下所示。
Widget attendanceHistory(List<History>
historyList)=>
DataTable(columns: <DataColumn>[
DataColumn(label: Text("Date"),),
DataColumn(label: Text("Time in" ),),
DataColumn(label: Text("Time out")
)],
rows:
historyList
?.map((element)=>DataRow(
cells: <DataCell>[
DataCell(Text(element?.date)),
DataCell(Text(element?.timeIn)),
DataCell(Text(element?.timeOut)),
]) )?.toList());
答案 1 :(得分:0)
当您将 null
值传递给 Text
小部件时会生成此错误。因此,为了避免这种情况,您可以在显示文本之前放置一个空检查条件,或者您可以将默认值传递给 Text
小部件。
Widget attendanceHistory(List<History> historyList)=>
DataTable(columns: <DataColumn>[
DataColumn(label: Text("Date"),),
DataColumn(label: Text("Time in" ),),
DataColumn(label: Text("Time out")
)],
rows:
historyList
.map((element)=>DataRow(
cells: <DataCell>[
DataCell(Text(element.date ?? "N/A")),
DataCell(Text(element.timeIn ?? "N/A")),
DataCell(Text(element.timeOut ?? "N/A")),
])
).toList());
Container(
padding: EdgeInsets.fromLTRB(15, 150, 0, 0),
child:SingleChildScrollView(
scrollDirection: Axis.vertical,
child: FutureBuilder( //This is line 171
future: _getRecord(),
builder: (BuildContext context, AsyncSnapshot<List<History>> snapshot) {
// Check if the data has been received.
if (snapshot.hasData) {
// Return the widget and provide the received data.
return attendanceHistory(snapshot.data);
}
return Center(child: CircularProgressIndicator(),);
}
),