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

Flutter中SharedPreferences返回最后保存布尔值异常求助

解决Flutter中SharedPreferences存储Person对象Joined状态的问题

问题根源

你现在的代码里,所有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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 03:55:42