如何为新 Screenroute 中的每个列表项提供自己的 Class 实例
How to provide own Class instance for each List item in new Screenroute
我想为 GroupData 中的每个组创建一个 TaskData 实例,并将其显示在新屏幕中,但我没有得到正确的方法。实际上,我在所有可用组中都有相同的任务列表。
任务功能运行良好。如果我点击复选标记,任务会被选中,但它会在所有可用组中发生。如何在每个组中获得一个新的任务列表?
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider<GroupData>(
create: (context) => GroupData(),
),
ChangeNotifierProvider<TaskData>(
create: (context) => TaskData(),
),
],
child: MaterialApp(
theme: ThemeData.dark().copyWith(
// scaffoldBackgroundColor: Color(0xFF3C3F40),
),
home: GroupsScreen(),
),
);
}
}
class GroupsScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
IconButton(
icon: Icon(
FontAwesomeIcons.plusCircle,
size: 30.0,
),
onPressed: () {
// Add group functionality
},
),
Expanded(
child: Consumer<GroupData>(
builder: (context, groupData, child) {
return ListView.builder(
itemBuilder: (context, index) {
final group = groupData.groups[index];
return GroupTile(
group: group,
);
},
itemCount: groupData.groupCount,
);
},
),
)
],
),
),
);
}
}
class GroupTile extends StatelessWidget {
final Group group;
GroupTile({
@required this.group,
});
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) {
return TasksScreen(
group: group,
);
},
),
);
},
child: Container(
margin: EdgeInsets.all(10.0),
child: Material(
borderRadius: BorderRadius.circular(10.0),
color: Color(0xFF626931),
child: Container(
padding: EdgeInsets.symmetric(
horizontal: 10.0,
vertical: 5.0,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
group.title,
style: TextStyle(fontSize: 18.0, fontWeight: FontWeight.w700),
),
Row(
children: <Widget>[
Text(
'12 Tasks',
style: TextStyle(
fontSize: 10.0,
fontWeight: FontWeight.bold,
color: Colors.white70,
),
),
],
),
],
),
),
),
),
);
}
}
class TasksScreen extends StatelessWidget {
final Group group;
TasksScreen({this.group});
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider.value(
value: group,
child: Scaffold(
body: SafeArea(
child: Column(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
IconButton(
icon: Icon(
FontAwesomeIcons.angleLeft,
size: 30.0,
),
onPressed: () {
Navigator.pop(context);
},
),
Text(
group.title,
style: TextStyle(
fontSize: 30.0,
fontWeight: FontWeight.bold,
),
),
IconButton(
icon: Icon(
FontAwesomeIcons.plusCircle,
size: 30.0,
),
onPressed: () {
// add task to group functionality
},
),
],
),
Expanded(
child: Consumer<TaskData>(
builder: (context, taskData, child) {
print(taskData);
return ListView.builder(
itemBuilder: (context, index) {
final task = taskData.tasks[index];
return TaskTile(
name: task.name,
isChecked: task.isDone,
onLongPressCallback: () {
taskData.deleteTask(task);
},
checkboxCallback: (checkboxState) {
taskData.updateTask(task);
},
);
},
itemCount: taskData.taskCount,
);
},
),
),
],
),
),
),
);
}
}
class TaskTile extends StatelessWidget {
final bool isChecked;
final String name;
final Function checkboxCallback;
final Function onLongPressCallback;
TaskTile(
{this.name,
this.isChecked,
this.checkboxCallback,
this.onLongPressCallback});
@override
Widget build(BuildContext context) {
return ListTile(
onLongPress: onLongPressCallback,
title: Text(
name,
style: TextStyle(
decoration: isChecked ? TextDecoration.lineThrough : null,
),
),
trailing: Checkbox(
value: isChecked,
onChanged: checkboxCallback,
),
);
}
}
class GroupData extends ChangeNotifier {
List<Group> _groups = [
Group(
title: 'Group 1',
),
Group(
title: 'Group 2',
),
];
get groups {
return _groups;
}
void updateGroupData() {
notifyListeners();
}
void addGroup(Group group) {
_groups.add(group);
notifyListeners();
}
get groupCount {
return groups.length;
}
}
class TaskData extends ChangeNotifier {
List<Task> _tasks = [
Task(name: 'Buy milk'),
Task(name: 'watch a movie'),
Task(name: 'have a coffee'),
];
get tasks {
return _tasks;
}
int get taskCount {
return _tasks.length;
}
void addTask(Task newTask) {
_tasks.add(newTask);
notifyListeners();
}
void updateTask(Task task) {
task.toggleIsDone();
notifyListeners();
}
void deleteTask(Task task) {
_tasks.remove(task);
notifyListeners();
}
}
class Group extends ChangeNotifier {
String title;
TaskData taskData;
Group({this.taskData, this.title});
}
class Task {
String name;
bool isDone;
Task({this.isDone = false, this.name});
void toggleIsDone() {
isDone = !isDone;
}
}
根据我从您的代码中看到的情况,您正在将数据从 taskData
变量传递到 task
变量,然后调用您的 TaskTile
.
为了处理每个单独的状态,您需要更新数组列表中的值,即 taskData
变量,
尝试将 taskData.task[index]
直接传递给您的 `TaskTile,然后它将处理单独的状态
ListView.builder(
itemBuilder: (context, index) {
return TaskTile(
name: taskData.tasks[index].name,
isChecked: taskData.tasks[index].isDone,
onLongPressCallback: () {
taskData.deleteTask(taskData.tasks[index]);
},
checkboxCallback: (checkboxState) {
taskData.updateTask(taskData.tasks[index]);
},
);
,
itemCount: taskData.taskCount,
);
GroupTile
也一样
感谢@Vicky Salunkhe 的回答,但你提到的内容已经存在。
经过 2 天的头脑风暴后,我找到了解决方案。
而不是这个:
class GroupTile extends StatelessWidget {
final Group group;
GroupTile({
@required this.group,
});
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) {
return TasksScreen(
group: group,
);
},
),
);
},
);
}
}
有效的解决方案是这样的:
使用 final TaskData taskData = TaskData();
创建一个新的 TaskData 实例
并使用这个新的 TaskData 实例创建一个具有现有实例的提供者:
ChangeNotifierProvider.value(
value: taskData,
child: TasksScreen(
group: group,
),
);
完整代码示例:
class GroupTile extends StatelessWidget {
@override
Widget build(BuildContext context) {
final group = Provider.of<Group>(context);
final TaskData taskData = TaskData();
return GestureDetector(
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) {
return ChangeNotifierProvider.value(
value: taskData,
child: TasksScreen(
group: group,
),
);
},
),
);
},
);
}
}
我想为 GroupData 中的每个组创建一个 TaskData 实例,并将其显示在新屏幕中,但我没有得到正确的方法。实际上,我在所有可用组中都有相同的任务列表。 任务功能运行良好。如果我点击复选标记,任务会被选中,但它会在所有可用组中发生。如何在每个组中获得一个新的任务列表?
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider<GroupData>(
create: (context) => GroupData(),
),
ChangeNotifierProvider<TaskData>(
create: (context) => TaskData(),
),
],
child: MaterialApp(
theme: ThemeData.dark().copyWith(
// scaffoldBackgroundColor: Color(0xFF3C3F40),
),
home: GroupsScreen(),
),
);
}
}
class GroupsScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
IconButton(
icon: Icon(
FontAwesomeIcons.plusCircle,
size: 30.0,
),
onPressed: () {
// Add group functionality
},
),
Expanded(
child: Consumer<GroupData>(
builder: (context, groupData, child) {
return ListView.builder(
itemBuilder: (context, index) {
final group = groupData.groups[index];
return GroupTile(
group: group,
);
},
itemCount: groupData.groupCount,
);
},
),
)
],
),
),
);
}
}
class GroupTile extends StatelessWidget {
final Group group;
GroupTile({
@required this.group,
});
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) {
return TasksScreen(
group: group,
);
},
),
);
},
child: Container(
margin: EdgeInsets.all(10.0),
child: Material(
borderRadius: BorderRadius.circular(10.0),
color: Color(0xFF626931),
child: Container(
padding: EdgeInsets.symmetric(
horizontal: 10.0,
vertical: 5.0,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
group.title,
style: TextStyle(fontSize: 18.0, fontWeight: FontWeight.w700),
),
Row(
children: <Widget>[
Text(
'12 Tasks',
style: TextStyle(
fontSize: 10.0,
fontWeight: FontWeight.bold,
color: Colors.white70,
),
),
],
),
],
),
),
),
),
);
}
}
class TasksScreen extends StatelessWidget {
final Group group;
TasksScreen({this.group});
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider.value(
value: group,
child: Scaffold(
body: SafeArea(
child: Column(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
IconButton(
icon: Icon(
FontAwesomeIcons.angleLeft,
size: 30.0,
),
onPressed: () {
Navigator.pop(context);
},
),
Text(
group.title,
style: TextStyle(
fontSize: 30.0,
fontWeight: FontWeight.bold,
),
),
IconButton(
icon: Icon(
FontAwesomeIcons.plusCircle,
size: 30.0,
),
onPressed: () {
// add task to group functionality
},
),
],
),
Expanded(
child: Consumer<TaskData>(
builder: (context, taskData, child) {
print(taskData);
return ListView.builder(
itemBuilder: (context, index) {
final task = taskData.tasks[index];
return TaskTile(
name: task.name,
isChecked: task.isDone,
onLongPressCallback: () {
taskData.deleteTask(task);
},
checkboxCallback: (checkboxState) {
taskData.updateTask(task);
},
);
},
itemCount: taskData.taskCount,
);
},
),
),
],
),
),
),
);
}
}
class TaskTile extends StatelessWidget {
final bool isChecked;
final String name;
final Function checkboxCallback;
final Function onLongPressCallback;
TaskTile(
{this.name,
this.isChecked,
this.checkboxCallback,
this.onLongPressCallback});
@override
Widget build(BuildContext context) {
return ListTile(
onLongPress: onLongPressCallback,
title: Text(
name,
style: TextStyle(
decoration: isChecked ? TextDecoration.lineThrough : null,
),
),
trailing: Checkbox(
value: isChecked,
onChanged: checkboxCallback,
),
);
}
}
class GroupData extends ChangeNotifier {
List<Group> _groups = [
Group(
title: 'Group 1',
),
Group(
title: 'Group 2',
),
];
get groups {
return _groups;
}
void updateGroupData() {
notifyListeners();
}
void addGroup(Group group) {
_groups.add(group);
notifyListeners();
}
get groupCount {
return groups.length;
}
}
class TaskData extends ChangeNotifier {
List<Task> _tasks = [
Task(name: 'Buy milk'),
Task(name: 'watch a movie'),
Task(name: 'have a coffee'),
];
get tasks {
return _tasks;
}
int get taskCount {
return _tasks.length;
}
void addTask(Task newTask) {
_tasks.add(newTask);
notifyListeners();
}
void updateTask(Task task) {
task.toggleIsDone();
notifyListeners();
}
void deleteTask(Task task) {
_tasks.remove(task);
notifyListeners();
}
}
class Group extends ChangeNotifier {
String title;
TaskData taskData;
Group({this.taskData, this.title});
}
class Task {
String name;
bool isDone;
Task({this.isDone = false, this.name});
void toggleIsDone() {
isDone = !isDone;
}
}
根据我从您的代码中看到的情况,您正在将数据从 taskData
变量传递到 task
变量,然后调用您的 TaskTile
.
为了处理每个单独的状态,您需要更新数组列表中的值,即 taskData
变量,
尝试将 taskData.task[index]
直接传递给您的 `TaskTile,然后它将处理单独的状态
ListView.builder(
itemBuilder: (context, index) {
return TaskTile(
name: taskData.tasks[index].name,
isChecked: taskData.tasks[index].isDone,
onLongPressCallback: () {
taskData.deleteTask(taskData.tasks[index]);
},
checkboxCallback: (checkboxState) {
taskData.updateTask(taskData.tasks[index]);
},
);
,
itemCount: taskData.taskCount,
);
GroupTile
感谢@Vicky Salunkhe 的回答,但你提到的内容已经存在。
经过 2 天的头脑风暴后,我找到了解决方案。
而不是这个:
class GroupTile extends StatelessWidget {
final Group group;
GroupTile({
@required this.group,
});
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) {
return TasksScreen(
group: group,
);
},
),
);
},
);
}
}
有效的解决方案是这样的:
使用 final TaskData taskData = TaskData();
创建一个新的 TaskData 实例
并使用这个新的 TaskData 实例创建一个具有现有实例的提供者:
ChangeNotifierProvider.value(
value: taskData,
child: TasksScreen(
group: group,
),
);
完整代码示例:
class GroupTile extends StatelessWidget {
@override
Widget build(BuildContext context) {
final group = Provider.of<Group>(context);
final TaskData taskData = TaskData();
return GestureDetector(
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) {
return ChangeNotifierProvider.value(
value: taskData,
child: TasksScreen(
group: group,
),
);
},
),
);
},
);
}
}