【问题标题】:How to provide own Class instance for each List item in new Screenroute如何为新 Screenroute 中的每个列表项提供自己的类实例
【发布时间】:2020-11-16 02:16:07
【问题描述】:

我想为 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;
  }
}

【问题讨论】:

    标签: flutter flutter-provider


    【解决方案1】:

    感谢@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,
                    ),
                  );
                },
              ),
            );
          },
        );
      }
    }
    
    

    【讨论】:

      【解决方案2】:

      我从您的代码中看到的是,您正在将数据从 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

      【讨论】:

        猜你喜欢
        • 2012-01-13
        • 1970-01-01
        • 2011-07-14
        • 1970-01-01
        • 2019-04-17
        • 1970-01-01
        • 2016-07-02
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多