Flutter中如何通过SharedPreferences持久化选中值,返回页面保持选中状态?
核心问题分析
你的代码存在三个关键问题导致返回页面后选中状态不恢复:
- 页面初始化时未从SharedPreferences读取并恢复保存的选中数据到
multipleSelected列表 - 取消选中项时未同步更新SharedPreferences中的数据
_onCategorySelected函数放在ListView.builder的itemBuilder内部,每次列表重建都会重复创建该函数,且异步操作与setState的顺序不合理
修复步骤及代码修改
1. 初始化时加载保存的选中数据
在initState中完成SharedPreferences的初始化,读取保存的字符串列表并转换为整数列表,赋值给multipleSelected后触发UI更新:
@override void initState() { super.initState(); _loadSelectedBases(); } Future<void> _loadSelectedBases() async { final pref = await SharedPreferences.getInstance(); List<String>? savedStrings = pref.getStringList("stringList"); if (savedStrings != null) { setState(() { // 将字符串列表转回整数列表 multipleSelected = savedStrings.map((s) => int.parse(s)).toList(); }); } }
2. 修复选中/取消选中时的SharedPreferences同步逻辑
- 将
_onCategorySelected移到itemBuilder外部,避免重复创建 - 无论是选中还是取消选中,都同步更新SharedPreferences中的数据
- 调整异步操作与
setState顺序,确保内存数据与本地存储一致
修改后的getDataBaseList方法及处理函数:
Widget getDataBaseList() { return FutureBuilder<List>( future: BasesService().GetBases(), builder: (context, snapshot) { List? baseNames = snapshot.data; print(baseNames); return ListView.builder( shrinkWrap: true, itemCount: baseNames?.length ?? 0, itemBuilder: (context, i) { return Column( children: [ ListTile( title: Padding( padding: const EdgeInsets.only(left: 1.0), child: Text( baseNames?[i]['name'] ?? 'not loading', style: TextStyle( fontFamily: 'fonts/Montserrat', fontSize: 24, fontWeight: FontWeight.w900, color: Colors.white), ), ), leading: Checkbox( activeColor: Colors.green, checkColor: Colors.green, side: BorderSide(width: 2, color: Colors.white), value: multipleSelected.contains(baseNames?[i]['id']), onChanged: (bool? selected) { if (selected != null) { _onCategorySelected(selected, baseNames?[i]['id']); } }, ), ), ], ); }, ); }, ); } // 独立的选中状态处理函数 Future<void> _onCategorySelected(bool selected, int id) async { final pref = await SharedPreferences.getInstance(); setState(() { if (selected) { if (!multipleSelected.contains(id)) { multipleSelected.add(id); } } else { multipleSelected.remove(id); } }); // 同步更新本地存储 List<String> stringsList = multipleSelected.map((i) => i.toString()).toList(); await pref.setStringList("stringList", stringsList); }
3. 优化变量类型(可选但推荐)
为避免类型混淆,将multipleSelected明确声明为整数列表:
List<int> multipleSelected = [];
其他注意事项
- 确保
baseNames?[i]['id']返回的是整数类型,否则字符串转整数时会抛出异常 - 由于
FutureBuilder会在数据加载完成后重建列表,而initState中的加载操作会提前完成,两者不会产生冲突
内容的提问来源于stack exchange,提问作者user16357470
相关产品推荐
相关产品推荐

