Flutter中使用sharedPreferences存取自定义列表bool字段数据
需求可行性结论
完全可以实现,且不需要存储全量列表数据。你的场景中id/num/name属于固定静态数据,硬编码在代码中不会变更,只有like/catched两个bool字段会随用户交互变化,只需要以每条数据的唯一id为标识,单独存储这两个变更的bool值即可,比全量序列化存储性能更好、维护成本更低。
具体实现步骤
1. 引入依赖
在pubspec.yaml中添加本地存储依赖:
dependencies: flutter: sdk: flutter shared_preferences: ^2.2.2
执行flutter pub get完成安装。
2. 修复原有交互逻辑的问题
你原有onTap回调里的写法有两个问题:一是取反操作没有读取当前条目的属性值,二是没有用setState触发UI刷新,修正后的交互逻辑如下:
onTap: () { setState(() { // 取当前条目的属性值取反 dlists.like = !dlists.like; dlists.catched = !dlists.catched; // 修改后立刻同步到本地存储 _saveSingleItemStatus(dlists); }); },
3. 实现单条状态存储方法
导入shared_preferences包,编写存储方法,用条目唯一id拼接存储key,避免和其他存储数据冲突:
import 'package:shared_preferences/shared_preferences.dart'; Future<void> _saveSingleItemStatus(DefinitiveList item) async { final prefs = await SharedPreferences.getInstance(); // 分别存储两个bool字段 await prefs.setBool('item_${item.id}_like', item.like); await prefs.setBool('item_${item.id}_catched', item.catched); }
4. 实现初始化读取逻辑
在页面的initState生命周期中调用读取方法,把本地存储的状态覆盖到初始静态列表上,完成状态恢复:
@override void initState() { super.initState(); _loadSavedStatus(); } Future<void> _loadSavedStatus() async { final prefs = await SharedPreferences.getInstance(); for (final item in definiti) { // 如果本地没存过值,就用代码里写的初始默认值 item.like = prefs.getBool('item_${item.id}_like') ?? item.like; item.catched = prefs.getBool('item_${item.id}_catched') ?? item.catched; } // 状态覆盖完成后刷新UI setState(() {}); }
这套逻辑不需要做任何全量列表的序列化操作,只存储变更的bool字段,存储空间占用极小,读写速度快,也不会出现反序列化字段匹配错误的问题。
补充:全量列表序列化存储实现方案
如果后续你的列表数据不是硬编码静态数据(比如从服务端拉取、可能动态调整),必须存储全量列表,可以通过给数据类加Map转换方法实现序列化,步骤如下:
- 给
DefinitiveList类添加序列化、反序列化方法:
class DefinitiveList { int id; String num; String name; bool like; bool catched; DefinitiveList( this.id, this.num, this.name, this.like, this.catched ); // 对象转可存储的Map结构 Map<String, dynamic> toMap() { return { 'id': id, 'num': num, 'name': name, 'like': like, 'catched': catched, }; } // 从Map结构还原对象 factory DefinitiveList.fromMap(Map<String, dynamic> map) { return DefinitiveList( map['id'] as int, map['num'] as String, map['name'] as String, map['like'] as bool, map['catched'] as bool, ); } }
- 存储时把整个列表转成
List<Map>结构,再转成json字符串通过shared_preferences存储;读取时把字符串解码成List<Map>,再通过fromMap方法还原成DefinitiveList对象列表即可。注意你当前的静态列表场景完全不需要用这套方案,前面的轻量存储方案已经完全满足需求。
内容的提问来源于stack exchange,提问作者Juan Sin Miedo
相关产品推荐
相关产品推荐

