Flutter中SharedPreferences返回最后保存布尔值异常求助
问题根源
你现在的代码里,所有Person的Joined状态都存在同一个SharedPreferences键"person_joined"下,这直接导致了以下问题:
- 当你把某一个Person的Joined设为true并保存时,这个键的值被覆盖成true,所有读取这个键的Person都会显示Joined为true。
- 重启应用后,这个键没有存储值,默认取false,所以所有Person的Joined都变成false;再修改一个时,键又被设为true,所有条目又跟着变true。
- 收藏页只读取这个单一的键值,自然会把所有符合日期条件的Person都显示出来。
修复步骤
1. 给每个Person分配唯一的存储键
在HomePage的savebool方法里,利用Firebase返回的Person['key'](也就是每条数据的唯一标识)拼接存储键,确保每个Person的状态存在独立的键里:
void savebool() async { SharedPreferences prefs = await SharedPreferences.getInstance(); // 用Person的唯一key拼接专属存储键 await prefs.setBool("person_${Person['key']}_joined", Person['Joined']); print("Person['Joined'] : ${Person['Joined']}"); }
同时,在初始化Person数据时,要从SharedPreferences读取对应键的本地状态,覆盖Firebase返回的默认值:
注意:因为itemBuilder不能直接是异步函数,建议把
listItem改成StatefulWidget,在它的initState里读取对应Person的Joined状态:
// 改造后的listItem为StatefulWidget class PersonListItem extends StatefulWidget { final Map Person; const PersonListItem({super.key, required this.Person}); @override State<PersonListItem> createState() => _PersonListItemState(); } class _PersonListItemState extends State<PersonListItem> { late Map _person; @override void initState() { super.initState(); _person = widget.Person; _loadLocalJoinedState(); } void _loadLocalJoinedState() async { SharedPreferences prefs = await SharedPreferences.getInstance(); bool localJoined = prefs.getBool("person_${_person['key']}_joined") ?? false; setState(() { _person['Joined'] = localJoined; }); } void savebool() async { SharedPreferences prefs = await SharedPreferences.getInstance(); await prefs.setBool("person_${_person['key']}_joined", _person['Joined']); } @override Widget build(BuildContext context) { return Slidable( startActionPane: ActionPane( motion: const BehindMotion(), extentRatio: 1 / 5, children: [ SlidableAction( backgroundColor: Colors.blue, icon: Icons.add, label: 'Join', onPressed: (BuildContext context) { setState(() { _person['Joined'] = true; }); savebool(); }, ), // 可选:添加取消Join的动作 SlidableAction( backgroundColor: Colors.red, icon: Icons.remove, label: 'Unjoin', onPressed: (BuildContext context) { setState(() { _person['Joined'] = false; }); savebool(); }, ) ], ), // 原有的列表项内容 child: ListTile( title: Text(_person['name'] ?? ''), // ...其他UI内容 ), ); } }
然后在FirebaseAnimatedList的itemBuilder里使用这个新的StatefulWidget:
itemBuilder: (BuildContext context, DataSnapshot snapshot, Animation<double> animation, int index) { Map Person = snapshot.value as Map; Person['key'] = snapshot.key; if (Person['Date'] == DateFormat("d-MM-yyyy").format(_selectedDate)) { return PersonListItem(Person: Person); } else { return Container(); } },
2. 修复收藏页的筛选逻辑
Favourites页不能再只读取单一的键,需要获取所有Person数据后,逐个读取对应的本地Joined状态,筛选出为true的条目:
late List<Map> _favouritePersons = []; @override void initState() { super.initState(); _loadFavouritePersons(); } void _loadFavouritePersons() async { SharedPreferences prefs = await SharedPreferences.getInstance(); // 从Firebase获取所有Person数据 QuerySnapshot snapshot = await dbRef.get(); List<Map> allPersons = snapshot.docs.map((doc) { Map person = doc.data() as Map; person['key'] = doc.id; return person; }).toList(); // 筛选出本地Joined为true的Person _favouritePersons = allPersons.where((person) { bool isJoined = prefs.getBool("person_${person['key']}_joined") ?? false; return isJoined; }).toList(); setState(() {}); } @override Widget build(BuildContext context) { return ListView.builder( itemCount: _favouritePersons.length, itemBuilder: (context, index) { // 渲染收藏的Person条目 return ListTile( title: Text(_favouritePersons[index]['name'] ?? ''), ); }, ); }
内容的提问来源于stack exchange,提问作者Tyrone
相关产品推荐
相关产品推荐

