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

如何在Flutter中使用SharedPreferences实现收藏按钮状态持久化

问题排查与修复:Flutter中SharedPreferences保存收藏状态失效

你的代码存在几个核心问题导致收藏状态无法持久化,下面逐一说明并给出修复方案:

核心问题分析

  • 共用单一存储key:你用is_save这个全局key存储所有收藏项状态,所有item的收藏状态会互相覆盖,无法区分不同item。
  • 未初始化加载本地存储:Provider初始化时没有从SharedPreferences读取已保存的收藏项,应用重启后_foundUsers列表为空,之前的收藏状态丢失。
  • Item对象判断逻辑错误:默认情况下Dart对象的contains和remove通过引用地址判断相等,若Item类未重写==和hashCode,即使两个item内容一致,也会被判定为不同对象,导致收藏状态判断失效。

修复后的完整代码

1. 先确保Item类重写相等判断方法

class Item {
  final String id; // 每个item必须有唯一标识,比如id
  final String name; // 示例字段,根据你的实际需求调整

  Item({required this.id, required this.name});

  // 重写==和hashCode,确保根据内容判断对象相等
  @override
  bool operator ==(Object other) =>
      identical(this, other) ||
      other is Item &&
          runtimeType == other.runtimeType &&
          id == other.id;

  @override
  int get hashCode => id.hashCode;
}

2. 修改FavoriteProvider类

import 'package:flutter/cupertino.dart';
import 'package:provider/provider.dart';
import 'package:shared_preferences/shared_preferences.dart';

class FavoriteProvider extends ChangeNotifier {
  List<Item> _foundUsers = [];
  List<Item> get words => _foundUsers;

  // 初始化时加载本地保存的收藏项
  FavoriteProvider() {
    _loadFavorites();
  }

  Future<void> _loadFavorites() async {
    final prefs = await SharedPreferences.getInstance();
    // 读取所有收藏的item id(这里假设你用id作为唯一标识)
    final favoriteIds = prefs.getStringList('favorite_items') ?? [];
    // 这里需要你根据实际场景,从数据源中获取对应的Item对象
    // 示例:如果你的所有item列表是allItems,那么筛选出id在favoriteIds中的项
    // _foundUsers = allItems.where((item) => favoriteIds.contains(item.id)).toList();
    // 注意:如果allItems是异步获取的,需要调整加载逻辑,确保数据加载完成后再执行此步骤
    notifyListeners();
  }

  Future<void> toggleFavorite(Item item) async {
    final prefs = await SharedPreferences.getInstance();
    final isExist = _foundUsers.contains(item);

    if (isExist) {
      _foundUsers.remove(item);
    } else {
      _foundUsers.add(item);
    }

    // 保存当前收藏的所有item id到本地
    final favoriteIds = _foundUsers.map((item) => item.id).toList();
    await prefs.setStringList('favorite_items', favoriteIds);

    notifyListeners();
  }

  bool isExist(Item item) {
    return _foundUsers.contains(item);
  }

  Future<void> clearFavorite() async {
    _foundUsers = [];
    final prefs = await SharedPreferences.getInstance();
    await prefs.remove('favorite_items');
    notifyListeners();
  }

  static FavoriteProvider of(
    BuildContext context, {
    bool listen = true,
  }) {
    return Provider.of<FavoriteProvider>(
      context,
      listen: listen,
    );
  }
}

3. UI部分保持不变(确保已正确获取Provider实例)

trailing: IconButton(
  onPressed: () {
    provider.toggleFavorite(word);
  },
  icon: provider.isExist(word)
      ? const Icon(Icons.favorite, color: Colors.red)
      : const Icon(Icons.favorite_border),
),

关键修复点说明

  • 用字符串列表存储收藏项标识:不再用单一布尔值,而是保存所有收藏item的唯一id列表,精准区分每个item的状态。
  • 初始化加载本地数据:在Provider构造函数中调用_loadFavorites,确保应用启动时从SharedPreferences恢复之前的收藏状态。
  • 修复对象相等判断:给Item类重写==和hashCode,保证contains和remove方法能正确识别相同内容的item。

内容的提问来源于stack exchange,提问作者imesem

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 09:50:59