Flutter - LateError (LateInitializationError: Field '_items@68190616' has not been initialized.)
Flutter - LateError (LateInitializationError: Field '_items@68190616' has not been initialized.)
我是 Flutter 的新手,目前正在尝试使用数据库中的一些数据显示在下拉 select 菜单中(使用 mysql1 and select_form_field packages)。 SelectFormField
需要传递一个 List<Map<String, dynamic>>
作为其 items:
参数。每当我尝试 运行 我的代码时,我都会收到异常 LateError (LateInitializationError: Field '_items@68190616' has not been initialized.).
环顾四周后,似乎在 initState()
中初始化我的项目列表应该可以解决问题,但我无法让它工作。下面是我的main.dart.
class MyCustomFormState extends State<MyCustomForm> {
...
late List<Map<String, dynamic>> _items;
@override
void initState() {
_getData();
super.initState();
}
_getData() async {
_items = await getData();
}
Widget build(BuildContext context) {
return Form(
key: _formKey,
child: Column(
children: <Widget>[
Container(
child: SelectFormField(
controller: nameController,
hintText: "...",
items: _items,
...
}
这是我的 database.dart 文件,它能够以我需要的 List<Map<String, dynamic>>
格式获取和格式化数据:
getData() async {
List<Map<String, dynamic>> items = <Map<String, dynamic>>[];
dynamic conn = await connect('database');
var results = await conn.query('select * from data');
for (var row in results) {
items.add({'value': row[0], 'label': row[1]});
}
await conn.close();
return items;
}
非常感谢任何帮助。谢谢!
尝试在 initState() 上创建空地图,然后再使用它。因为当进入构建阶段时,它会访问引发错误的空映射。
@override
void initState() {
_items = <Map<String,dynamic>>[] // Empty one
_items = _getData(); // Or you can assign it immediately
super.initState();
}
编辑:尝试将 Initiate 与 initState
分开,因为你向我展示的错误是必须是 Future as await
并将其转换为所需的类型(在本例中为 List<Map<String, dynamic>>
)
@override
void initState() {
_getDataInit();
super.initState();
}
void _getDataInit() async {
_items = await _getData() as List<Map<String, dynamic>>;
}
Edit2:经过调查,发现 Future 的实现是错误的。我添加了 FutureBuilder
并删除了 initState
和 _items
变量来解决这个问题,这里是工作代码(只需将其粘贴为 form.dart):
import 'database.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:select_form_field/select_form_field.dart';
import 'package:date_time_picker/date_time_picker.dart';
class MyCustomForm extends StatefulWidget {
const MyCustomForm({Key? key}) : super(key: key);
@override
MyCustomFormState createState() {
return MyCustomFormState();
}
}
class MyCustomFormState extends State<MyCustomForm> {
final _formKey = GlobalKey<FormState>();
var nameController = TextEditingController();
var dateController = TextEditingController();
var courseController = TextEditingController();
var scoreController = TextEditingController();
final dateFormat = DateFormat('dd-MM-yyyy');
final database = Database();
@override
void dispose() {
nameController.dispose();
dateController.dispose();
courseController.dispose();
scoreController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
bool shouldDisplay = false;
return Form(
key: _formKey,
child: FutureBuilder<List<Map<String, dynamic>>>(
future: database.getBandits(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(
child: CircularProgressIndicator(),
);
} else {
if (snapshot.hasError) {
return ErrorWidget(Exception(
'Error occured when fetching data from database'));
} else if (!snapshot.hasData) {
return const Center(child: Text('Bandit is empty!'));
} else {
return Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Container(
padding: const EdgeInsets.symmetric(
vertical: 10.0, horizontal: 30.0),
child: SelectFormField(
controller: nameController,
hintText: "...",
items: snapshot.data,
validator: (value) {
if (value == null || value.isEmpty) {
return "Hvem er du?";
}
return null;
},
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: 'Bandit',
prefixIcon: Align(
widthFactor: 1.0,
heightFactor: 1.0,
child: Icon(Icons.person),
),
suffixIcon: Align(
widthFactor: 1.0,
heightFactor: 1.0,
child: Icon(Icons.arrow_drop_down),
)),
),
),
Container(
padding: const EdgeInsets.symmetric(
vertical: 10.0, horizontal: 30.0),
child: DateTimePicker(
controller: dateController,
validator: (value) {
if (value == null || value.isEmpty) {
setState(() {
dateController.text =
dateFormat.format(DateTime.now()).toString();
});
}
return null;
},
type: DateTimePickerType.date,
dateMask: 'dd-MM-yyyy',
firstDate: DateTime(2020),
lastDate: DateTime(2050),
dateLabelText: 'Dato',
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: 'Dato',
prefixIcon: Align(
widthFactor: 1.0,
heightFactor: 1.0,
child: Icon(Icons.date_range),
)),
),
),
Container(
padding: const EdgeInsets.symmetric(
vertical: 10.0, horizontal: 30.0),
child: TextFormField(
controller: courseController,
validator: (value) {
if (value == null || value.isEmpty) {
setState(() {
courseController.text = "HJGK";
});
}
return null;
},
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: 'Bane',
prefixIcon: Align(
widthFactor: 1.0,
heightFactor: 1.0,
child: Icon(Icons.golf_course),
)),
),
),
Container(
padding: const EdgeInsets.symmetric(
vertical: 10.0, horizontal: 30.0),
child: TextFormField(
controller: scoreController,
validator: (value) {
if (value == null || value.isEmpty) {
return "Indtast score";
}
return null;
},
keyboardType: TextInputType.number,
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: 'Score',
prefixIcon: Align(
widthFactor: 1.0,
heightFactor: 1.0,
child: Icon(Icons.sports_score)),
),
)),
ElevatedButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
_formKey.currentState!.save();
shouldDisplay = !shouldDisplay;
}
shouldDisplay
? showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: const Text("Score registreret"),
content: SingleChildScrollView(
child: ListBody(
children: <Widget>[
Padding(
padding:
const EdgeInsets.symmetric(
vertical: 10),
child: Text(
"Spiller: ${nameController.text}"),
),
Padding(
padding:
const EdgeInsets.symmetric(
vertical: 10),
child: Text(
"Dato: ${dateController.text}"),
),
Padding(
padding:
const EdgeInsets.symmetric(
vertical: 10),
child: Text(
"Bane: ${courseController.text}"),
),
Padding(
padding:
const EdgeInsets.symmetric(
vertical: 10),
child: Text(
"Score: ${scoreController.text}"),
),
],
),
),
actions: <Widget>[
TextButton(
child: const Text('OK'),
onPressed: () {
Navigator.of(context).pop();
},
),
],
);
},
)
: null;
},
child: const Text("Submit")),
],
);
}
}
}),
);
}
}
我是 Flutter 的新手,目前正在尝试使用数据库中的一些数据显示在下拉 select 菜单中(使用 mysql1 and select_form_field packages)。 SelectFormField
需要传递一个 List<Map<String, dynamic>>
作为其 items:
参数。每当我尝试 运行 我的代码时,我都会收到异常 LateError (LateInitializationError: Field '_items@68190616' has not been initialized.).
环顾四周后,似乎在 initState()
中初始化我的项目列表应该可以解决问题,但我无法让它工作。下面是我的main.dart.
class MyCustomFormState extends State<MyCustomForm> {
...
late List<Map<String, dynamic>> _items;
@override
void initState() {
_getData();
super.initState();
}
_getData() async {
_items = await getData();
}
Widget build(BuildContext context) {
return Form(
key: _formKey,
child: Column(
children: <Widget>[
Container(
child: SelectFormField(
controller: nameController,
hintText: "...",
items: _items,
...
}
这是我的 database.dart 文件,它能够以我需要的 List<Map<String, dynamic>>
格式获取和格式化数据:
getData() async {
List<Map<String, dynamic>> items = <Map<String, dynamic>>[];
dynamic conn = await connect('database');
var results = await conn.query('select * from data');
for (var row in results) {
items.add({'value': row[0], 'label': row[1]});
}
await conn.close();
return items;
}
非常感谢任何帮助。谢谢!
尝试在 initState() 上创建空地图,然后再使用它。因为当进入构建阶段时,它会访问引发错误的空映射。
@override
void initState() {
_items = <Map<String,dynamic>>[] // Empty one
_items = _getData(); // Or you can assign it immediately
super.initState();
}
编辑:尝试将 Initiate 与 initState
分开,因为你向我展示的错误是必须是 Future as await
并将其转换为所需的类型(在本例中为 List<Map<String, dynamic>>
)
@override
void initState() {
_getDataInit();
super.initState();
}
void _getDataInit() async {
_items = await _getData() as List<Map<String, dynamic>>;
}
Edit2:经过调查,发现 Future 的实现是错误的。我添加了 FutureBuilder
并删除了 initState
和 _items
变量来解决这个问题,这里是工作代码(只需将其粘贴为 form.dart):
import 'database.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:select_form_field/select_form_field.dart';
import 'package:date_time_picker/date_time_picker.dart';
class MyCustomForm extends StatefulWidget {
const MyCustomForm({Key? key}) : super(key: key);
@override
MyCustomFormState createState() {
return MyCustomFormState();
}
}
class MyCustomFormState extends State<MyCustomForm> {
final _formKey = GlobalKey<FormState>();
var nameController = TextEditingController();
var dateController = TextEditingController();
var courseController = TextEditingController();
var scoreController = TextEditingController();
final dateFormat = DateFormat('dd-MM-yyyy');
final database = Database();
@override
void dispose() {
nameController.dispose();
dateController.dispose();
courseController.dispose();
scoreController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
bool shouldDisplay = false;
return Form(
key: _formKey,
child: FutureBuilder<List<Map<String, dynamic>>>(
future: database.getBandits(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(
child: CircularProgressIndicator(),
);
} else {
if (snapshot.hasError) {
return ErrorWidget(Exception(
'Error occured when fetching data from database'));
} else if (!snapshot.hasData) {
return const Center(child: Text('Bandit is empty!'));
} else {
return Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Container(
padding: const EdgeInsets.symmetric(
vertical: 10.0, horizontal: 30.0),
child: SelectFormField(
controller: nameController,
hintText: "...",
items: snapshot.data,
validator: (value) {
if (value == null || value.isEmpty) {
return "Hvem er du?";
}
return null;
},
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: 'Bandit',
prefixIcon: Align(
widthFactor: 1.0,
heightFactor: 1.0,
child: Icon(Icons.person),
),
suffixIcon: Align(
widthFactor: 1.0,
heightFactor: 1.0,
child: Icon(Icons.arrow_drop_down),
)),
),
),
Container(
padding: const EdgeInsets.symmetric(
vertical: 10.0, horizontal: 30.0),
child: DateTimePicker(
controller: dateController,
validator: (value) {
if (value == null || value.isEmpty) {
setState(() {
dateController.text =
dateFormat.format(DateTime.now()).toString();
});
}
return null;
},
type: DateTimePickerType.date,
dateMask: 'dd-MM-yyyy',
firstDate: DateTime(2020),
lastDate: DateTime(2050),
dateLabelText: 'Dato',
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: 'Dato',
prefixIcon: Align(
widthFactor: 1.0,
heightFactor: 1.0,
child: Icon(Icons.date_range),
)),
),
),
Container(
padding: const EdgeInsets.symmetric(
vertical: 10.0, horizontal: 30.0),
child: TextFormField(
controller: courseController,
validator: (value) {
if (value == null || value.isEmpty) {
setState(() {
courseController.text = "HJGK";
});
}
return null;
},
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: 'Bane',
prefixIcon: Align(
widthFactor: 1.0,
heightFactor: 1.0,
child: Icon(Icons.golf_course),
)),
),
),
Container(
padding: const EdgeInsets.symmetric(
vertical: 10.0, horizontal: 30.0),
child: TextFormField(
controller: scoreController,
validator: (value) {
if (value == null || value.isEmpty) {
return "Indtast score";
}
return null;
},
keyboardType: TextInputType.number,
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: 'Score',
prefixIcon: Align(
widthFactor: 1.0,
heightFactor: 1.0,
child: Icon(Icons.sports_score)),
),
)),
ElevatedButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
_formKey.currentState!.save();
shouldDisplay = !shouldDisplay;
}
shouldDisplay
? showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: const Text("Score registreret"),
content: SingleChildScrollView(
child: ListBody(
children: <Widget>[
Padding(
padding:
const EdgeInsets.symmetric(
vertical: 10),
child: Text(
"Spiller: ${nameController.text}"),
),
Padding(
padding:
const EdgeInsets.symmetric(
vertical: 10),
child: Text(
"Dato: ${dateController.text}"),
),
Padding(
padding:
const EdgeInsets.symmetric(
vertical: 10),
child: Text(
"Bane: ${courseController.text}"),
),
Padding(
padding:
const EdgeInsets.symmetric(
vertical: 10),
child: Text(
"Score: ${scoreController.text}"),
),
],
),
),
actions: <Widget>[
TextButton(
child: const Text('OK'),
onPressed: () {
Navigator.of(context).pop();
},
),
],
);
},
)
: null;
},
child: const Text("Submit")),
],
);
}
}
}),
);
}
}