Flutter待办列表页面刷新后任务数据重置丢失问题
问题根因
你把任务列表L、输入框显隐状态b都定义在了Tasks这个StatefulWidget的属性上,这是刷新后数据丢失的核心原因:
Flutter在触发组件重建(热重载、父组件重绘、键盘弹出收起触发的视图刷新等场景)时,会重新初始化Widget实例的所有属性,你之前追加到
L里的新增任务,会被直接重置成初始传入的默认值。
另外你直接修改widget.L的写法也不符合Flutter设计规范:Widget本身是不可变的配置载体,直接修改它持有的属性本身就会导致状态不可控。
修复步骤
- 将组件内部需要维护的可变状态(任务列表、输入框显隐状态)全部移动到对应的
_TasksState类中,不要在Widget层存储会变化的数据 - 新增任务时直接修改State内部维护的列表,再通过
setState触发UI更新 - 修正代码里的拼写问题:任务类的
tite字段拼写错误,类名tasks按照Dart规范应当首字母大写,避免和组件类名重名可以命名为TaskItem
修复后可直接运行的代码
// 修正任务实体类的命名和字段拼写 class TaskItem { final String title; final List subTasks; TaskItem(this.title, this.subTasks); } class Tasks extends StatefulWidget { // 仅作为初始化传参入口,不在这里存储可变状态 final List<TaskItem> initTasks; final bool initInputVisible; const Tasks(this.initTasks, this.initInputVisible, {super.key}); @override State<Tasks> createState() => _TasksState(); } class _TasksState extends State<Tasks> { final TextEditingController ctrl = TextEditingController(); // 可变状态全部存在State中,组件重建时不会丢失 late List<TaskItem> taskList; late bool inputVisible; @override void initState() { super.initState(); // 初始化时读取widget传入的初始值 taskList = List.from(widget.initTasks); inputVisible = widget.initInputVisible; } @override void dispose() { ctrl.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Column(children: [ Visibility( maintainInteractivity: true, maintainState: true, maintainSize: true, maintainAnimation: true, visible: inputVisible, child: TextField( controller: ctrl, focusNode: FocusNode(descendantsAreFocusable: true), onSubmitted: (text) { if (text.trim().isEmpty) return; setState(() { // 修改State内部维护的列表 taskList.add(TaskItem(text.trim(), [])); ctrl.clear(); }); }, decoration: const InputDecoration(fillColor: Colors.white, hintText: "输入任务后回车提交"), style: const TextStyle(color: Colors.white, fontWeight: FontWeight.w400), ), ), Expanded( child: ListView.builder( itemCount: taskList.length, itemBuilder: (BuildContext context, int index) { return Card( color: Colors.black, child: Column( children: [ ListTile( textColor: Colors.white, iconColor: Colors.white, title: Row(children: [ Checkbox( value: false, checkColor: const Color.fromRGBO(85, 85, 85, 1), tristate: false, onChanged: (value) {}, ), Text(taskList[index].title) ]), ), ], ), ); }, ) ) ]); } }
额外说明
如果后续需要从父组件修改任务列表、控制输入框显隐,通过didUpdateWidget生命周期监听父组件传入的新配置,同步更新State内部的状态即可,不要直接把可变状态存在Widget属性上。
内容的提问来源于stack exchange,提问作者B H
相关产品推荐
相关产品推荐

