英文:
List not populating in Flutter
问题
我正在尝试创建一个表单,当我填写它时,将填充一个ListView,但似乎无法使列表填充任何值。
我正在使用以下代码来创建底部导航:
class _AppState extends State<App> {
int _currentIndex = 0;
final List<Widget> body = [
AddNewStudent(),
StudentList(),
];
在一个包含表单的文件中,代码如下:
class StudentClass {
String kidFirstName;
String kidLastName;
DateTime dateOfBirth;
int totalAttendance = 0;
int attendanceAtRank = 0;
StudentClass(
{required this.kidFirstName,
required this.kidLastName,
required this.dateOfBirth});
}
class AddNewStudent extends StatefulWidget {
@override
AddStudentScreen createState() => AddStudentScreen();
}
class AddStudentScreen extends State<AddNewStudent> {
List<StudentClass> studentList = [];
void addStudent(StudentClass newStudent) {
setState(() {
studentList.add(newStudent);
});
}
final formKey = GlobalKey<FormState>();
Widget build(BuildContext context) {
return Container(
margin: EdgeInsets.all(20.0),
child: SingleChildScrollView(
child: Column(
children: [
Form(
key: formKey,
child: Column(
children: [
kidsFirstNameFormField(),
kidLastNameFormField(),
kidDateOfBirth(),
submitButton(),
],
),
),
],
)));
}
Widget submitButton() {
return ElevatedButton(
child: Text('Create New Student Profile'),
onPressed: () {
if (formKey.currentState?.validate() ?? false) {
formKey.currentState?.save();
StudentClass newStudent = StudentClass(
kidFirstName: kidFirstName,
kidLastName: kidLastName,
dateOfBirth: dateOfBirth,
);
addStudent(newStudent);
formKey.currentState?.reset();
}
},
);
}
ListView构建器在它自己的文件中:
class StudentList extends StatelessWidget {
@override
Widget build(BuildContext context) {
List<StudentClass> studentList = [];
return Scaffold(
appBar: AppBar(
title: Text('Student List'),
),
body: StudentListState(
studentList: studentList,
),
);
}
}
class StudentListState extends StatefulWidget {
final List<StudentClass> studentList;
StudentListState({required this.studentList});
@override
_StudentListState createState() => _StudentListState();
}
class _StudentListState extends State<StudentListState> {
void addStudent(StudentClass student) {
setState(() {
widget.studentList.add(student);
});
}
@override
Widget build(BuildContext context) {
return Container(
margin: EdgeInsets.all(20.0),
child: ListView.builder(
itemCount: widget.studentList.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(widget.studentList[index].kidFirstName),
subtitle: Text(widget.studentList[index].kidLastName),
trailing: Text(widget.studentList[index].dateOfBirth.toString()),
);
},
));
}
}
我在弄清如何将信息传递到列表以进行填充方面遇到了困难。我已经成功构建了没有错误,但我知道我没有正确传递信息。我知道我可能在这里有一个额外的列表。
英文:
I am trying to have a form when I fill it out will populate a ListView, but can't seem to get the list to popluate with any values.
I am using the following to have a bottom navigation:
class _AppState extends State<App> {
int _currentIndex = 0;
final List<Widget> body = [
AddNewStudent(),
StudentList(),
];
In a file that has the form looks like this:
class StudentClass {
String kidFirstName;
String kidLastName;
DateTime dateOfBirth;
int totalAttedance = 0;
int attedanceAtRank = 0;
StudentClass(
{required this.kidFirstName,
required this.kidLastName,
required this.dateOfBirth});
}
class AddNewStudent extends StatefulWidget {
@override
AddStudentScreen createState() => AddStudentScreen();
}
class AddStudentScreen extends State<AddNewStudent> {
List<StudentClass> studentList = [];
void addStudent(StudentClass newStudent) {
setState(() {
studentList.add(newStudent);
});
}
final formKey = GlobalKey<FormState>();
Widget build(BuildContext context) {
return Container(
margin: EdgeInsets.all(20.0),
child: SingleChildScrollView(
child: Column(
children: [
Form(
key: formKey,
child: Column(
children: [
kidsFirstNameFormField(),
kidLastNameFormField(),
kidDateofBirth(),
submitButton(),
],
),
),
],
)));
}
Widget submitButton() {
return ElevatedButton(
child: Text('Create New Student Profile'),
onPressed: () {
if (formKey.currentState?.validate() ?? false) {
formKey.currentState?.save();
StudentClass newStudent = StudentClass(
kidFirstName: kidFirstName,
kidLastName: kidLastName,
dateOfBirth: dateOfBirth,
);
addStudent(newStudent);
formKey.currentState?.reset();
}
},
);
}
The listview builder is in its own file:
class StudentList extends StatelessWidget {
@override
Widget build(BuildContext context) {
List<StudentClass> studentList = [];
return Scaffold(
appBar: AppBar(
title: Text('Student List'),
),
body: StudentListState(
studentList: studentList,
),
);
}
}
class StudentListState extends StatefulWidget {
final List<StudentClass> studentList;
StudentListState({required this.studentList});
@override
_StudentListState createState() => _StudentListState();
}
class _StudentListState extends State<StudentListState> {
void addStudent(StudentClass student) {
setState(() {
widget.studentList.add(student);
});
}
@override
Widget build(BuildContext context) {
return Container(
margin: EdgeInsets.all(20.0),
child: ListView.builder(
itemCount: widget.studentList.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(widget.studentList[index].kidFirstName),
subtitle: Text(widget.studentList[index].kidLastName),
trailing: Text(widget.studentList[index].dateOfBirth.toString()),
);
},
));
}
}
I am pretty stuck on figuring out how to pass the information over to the list to populate. I have gotten it to build with no errors but somehow I know I am not passing it correctly. I know I might have an extra list in here.
答案1
得分: 1
你正在更新AddStudentScreen
小部件的studentList
。在ListView
中,您正在渲染来自StudentList
小部件的studentList
,这是一个不同的变量并且始终为空。
此外,您在build
函数内初始化了studentList
,这意味着每次调用setState()
时,studentList
都会被初始化为空列表。
看起来您想在多个小部件中使用相同的数据。在这种情况下,考虑使用状态管理器。
对于您的情况,我建议您使用stream_mixin。
示例:
- 使用
stream_mixin
包创建学生服务StoreService
。
class StudentModel extends BaseModel { // 注意这一点
String kidFirstName;
String kidLastName;
DateTime dateOfBirth;
int totalAttedance = 0;
int attedanceAtRank = 0;
StudentModel({
required this.kidFirstName,
required this kidLastName,
required this dateOfBirth,
required String id,
}) : super(id: id);
}
class StudentService extends StoreService<StudentModel> { // 注意这一点
StudentService._();
static StudentService store = StudentService._(); // 仅创建了StudentService的单例。
}
- 向存储中添加学生数据(注意,这可以在应用程序的任何地方完成):
const student = new StudentModel(
// 在这里添加学生数据
)
StudentService.store.add(student);
- 渲染学生列表
StreamBuilder<StudentModel>(
stream: StudentService.store.onChange,
builder: (context, snapshot) {
if (snapshot.data == null) {
return Text("尚未添加学生。");
}
return ListView.builder(
itemCount: StudentService.store.values.length,
itemBuilder: (context, index) {
const student = StudentService.store.values[index];
return ListTile(
title: Text(student.kidFirstName),
subtitle: Text(student.kidLastName),
trailing: Text(student.dateOfBirth.toString()),
);
},
)
},
)
现在,每当您使用StudentService.store.add()
添加学生数据时,它将发出一个事件,您的SteamBuilder
会监听stream: StudentService.store.onChange
,并更新UI以显示更新的列表。
这还将消除使用StatefulWidget
的必要性。这意味着除非您需要为其他事情使用StatefulWidget
,否则只能使用StatelessWidget
。
英文:
You are updating the studentList
of the AddStudentScreen
widget. And in the ListView
you are rendering the studentList
from StudentList
widget which is a different variable and is always empty.
Also, you are initialising studentList
inside the build
function which means that on every setState()
studentList
will be initialised to an empty list.
Seems like you want to use the same data in multiple widgets. In such cases consider using a state manager.
For you scenario, I'd recommend you use stream_mixin.
Example:
- Create student service using
StoreService
fromstream_mixin
package.
class StudentModel extends BaseModel { // NOTICE THIS
String kidFirstName;
String kidLastName;
DateTime dateOfBirth;
int totalAttedance = 0;
int attedanceAtRank = 0;
StudentModel({
required this.kidFirstName,
required this.kidLastName,
required this.dateOfBirth,
required String id,
}) : super(id: id);
}
class StudentService extends StoreService<StudentModel> { // NOTICE THIS
StudentService._();
static StudentService store = StudentService._(); // Just creating a singleton for StudentService.
}
- To add student data in the store (note, this can be done anywhere in the app):
const student = new StudentModel(
// add student data here
)
StudentService.store.add(student);
- Render this list of students
StreamBuilder<StudentModel>(
stream: StudentService.store.onChange,
builder: (context, snapshot) {
if (snapshot.data == null) {
return Text("No student added yet.");
}
return ListView.builder(
itemCount: StudentService.store.values.length,
itemBuilder: (context, index) {
const student = StudentService.store.values[index];
return ListTile(
title: Text(student.kidFirstName),
subtitle: Text(student.kidLastName),
trailing: Text(student.dateOfBirth.toString()),
);
},
)
},
)
Now, every time you add student data using StudentService.store.add()
, it will emit an event which your SteamBuilder
with stream: StudentService.store.onChange
is listening and will update the UI to show the updated list.
This will also eliminate the necessity of StatefulWidget
. Which means you can use only StatelessWidget
unless otherwise you require StatefulWidget
for something else.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论