Flutter饮水提醒APP页面切换数据重置问题求助
Flutter饮水提醒APP状态重置问题解决方法
问题核心
切换页面后计数器和当日记录重置,本质是页面状态未做持久化存储,且你之前尝试的SharedPreferences用法存在多处错误:
- 直接将
ValueNotifier<List<DrinkRecordModel>>强转为List<String>,无法正确序列化自定义模型 _getData方法未将读取到的赋值给变量,仅调用了读取方法但未更新状态- 数据发生变化时未触发保存操作
分步修复方案
1. 给自定义模型添加序列化能力
SharedPreferences只能存储基础数据类型,需要把DrinkRecordModel转成可序列化的格式(比如JSON),修改模型类:
import 'dart:convert'; class DrinkRecordModel { final String time; final String amountOfWater; DrinkRecordModel({required this.time, required this.amountOfWater}); // 转成Map用于序列化 Map<String, dynamic> toMap() { return { 'time': time, 'amountOfWater': amountOfWater, }; } // 从Map反序列化回模型 factory DrinkRecordModel.fromMap(Map<String, dynamic> map) { return DrinkRecordModel( time: map['time'] ?? '', amountOfWater: map['amountOfWater'] ?? '', ); } }
2. 修复SharedPreferences操作逻辑
修改首页的存储和读取方法,正确处理数据持久化:
import 'dart:convert'; import 'package:shared_preferences/shared_preferences.dart'; class _HomeState extends State<Home> { static const _amountKey = 'total_drink_amount'; static const _recordsKey = 'drink_records_list'; late ValueNotifier<List<DrinkRecordModel>> _items; double amount = 0; // 保存数据到本地 void _saveData() async { final prefs = await SharedPreferences.getInstance(); // 保存总饮水量 await prefs.setDouble(_amountKey, amount); // 将记录列表转成JSON字符串列表存储 final recordsJson = _items.value.map((record) => jsonEncode(record.toMap())).toList(); await prefs.setStringList(_recordsKey, recordsJson); } // 从本地加载数据 Future<void> _getData() async { final prefs = await SharedPreferences.getInstance(); setState(() { // 读取总饮水量,默认值为0 amount = prefs.getDouble(_amountKey) ?? 0; // 读取记录并反序列化 final recordsJson = prefs.getStringList(_recordsKey); if (recordsJson != null) { _items.value = recordsJson.map((json) => DrinkRecordModel.fromMap(jsonDecode(json))).toList(); } else { // 无本地数据时初始化默认记录 _items.value = [ DrinkRecordModel( time: '11:00 AM', amountOfWater: changeUnit(), ), ]; } }); }
3. 正确初始化和触发保存
- 在页面初始化时加载本地数据:
@override void initState() { super.initState(); _items = ValueNotifier([]); _getData(); // 启动时加载保存的数据 }
- 在所有数据变化的场景调用保存方法:
- 点击添加饮水量时:
onTap: () { setState(() { widget.unit == 'kilograms' ? amount += 175 : amount += 6; _items.value.add(DrinkRecordModel( time: TimeOfDay.now().format(context), amountOfWater: changeUnit(), )); }); _saveData(); // 保存更新后的数据 },- 删除记录时(注意同步更新总饮水量):
void _deleteItem(int index) { final deletedRecord = _items.value[index]; final deletedAmount = double.parse(deletedRecord.amountOfWater.split(' ')[0]); setState(() { _items.value.removeAt(index); amount -= deletedAmount; }); _saveData(); }- 编辑记录完成后:
ElevatedButton( child: Text('Save'), onPressed: () { _items.notifyListeners(); Navigator.pop(context); _saveData(); // 保存编辑后的记录 }, )
4. 避免页面重建导致状态丢失
如果切换页面时首页被销毁重建,上述持久化逻辑会在initState重新加载数据,完全覆盖初始化的默认值,确保状态不会丢失。
内容的提问来源于stack exchange,提问作者Fatima
相关产品推荐
相关产品推荐

