You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter中如何通过SharedPreferences持久化选中值,返回页面保持选中状态?

解决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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 18:41:04