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

Flutter中使用shared_preferences实现大量收藏按钮本地存储的方案咨询

Flutter 多条目收藏功能SharedPreferences落地实现方案

1. 重构全局收藏管理工具类

不要零散定义上百个bool类型全局变量,统一封装单例管理类维护所有收藏状态,避免变量混乱。
修改globals.dart代码如下:

library prj.com.globals;
import 'package:flutter/foundation.dart';
import 'package:shared_preferences/shared_preferences.dart';

class FavoriteManager {
  static final FavoriteManager _instance = FavoriteManager._internal();
  factory FavoriteManager() => _instance;
  FavoriteManager._internal();

  late SharedPreferences _prefs;
  // 存储key前缀,避免和其他本地存储项冲突
  final String _keyPrefix = 'favorite_item_';
  // 状态更新通知器,用于跨页面同步状态
  final ValueNotifier<String?> updateNotifier = ValueNotifier(null);

  // APP启动时调用一次完成初始化
  Future<void> init() async {
    _prefs = await SharedPreferences.getInstance();
  }

  // 获取指定条目的收藏状态,默认未收藏
  bool getFavoriteStatus(String itemId) {
    return _prefs.getBool('$_keyPrefix$itemId') ?? false;
  }

  // 更新指定条目的收藏状态
  Future<void> setFavoriteStatus(String itemId, bool isFavorite) async {
    await _prefs.setBool('$_keyPrefix$itemId', isFavorite);
    // 发送状态更新通知
    updateNotifier.value = itemId;
  }

  // 可选:获取所有已收藏的条目ID,用于收藏列表页
  List<String> getAllFavorites() {
    return _prefs.getKeys()
        .where((key) => key.startsWith(_keyPrefix))
        .map((key) => key.replaceFirst(_keyPrefix, ''))
        .toList();
  }
}
// 全局可直接调用的单例实例
final favoriteManager = FavoriteManager();

在main.dart中完成初始化:

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  // 初始化收藏管理工具
  await favoriteManager.init();
  runApp(const MyApp());
}

2. 封装通用收藏按钮组件

不用每个业务页面都重复写收藏点击逻辑,抽离成通用组件,上百个页面直接复用即可。
新建common_favorite_button.dart:

import 'package:flutter/material.dart';
import 'globals.dart';

class CommonFavoriteButton extends StatefulWidget {
  // 传入当前条目唯一ID,对应你原来的后缀,比如0_01、0_02
  final String itemId;
  const CommonFavoriteButton({super.key, required this.itemId});

  @override
  State<CommonFavoriteButton> createState() => _CommonFavoriteButtonState();
}

class _CommonFavoriteButtonState extends State<CommonFavoriteButton> {
  late bool _isFavorite;

  @override
  void initState() {
    super.initState();
    // 初始化读取本地存储的收藏状态
    _isFavorite = favoriteManager.getFavoriteStatus(widget.itemId);
  }

  void _toggleFavorite() async {
    final newStatus = !_isFavorite;
    setState(() {
      _isFavorite = newStatus;
    });
    // 同步更新到本地存储
    await favoriteManager.setFavoriteStatus(widget.itemId, newStatus);
  }

  @override
  Widget build(BuildContext context) {
    return IconButton(
      onPressed: _toggleFavorite,
      icon: _isFavorite
          ? Icon(Icons.bookmark_rounded, color: Colors.yellow[800], size: 30)
          : Icon(Icons.bookmark_add_outlined, color: Colors.yellow[800], size: 30),
    );
  }
}

3. 改造原有业务代码

3.1 改造业务页面

删除home0_01.dart等页面里重复的save、delete方法,直接替换成通用组件即可,比如原来的actions部分修改为:

actions: <Widget>[
  CommonFavoriteButton(itemId: '0_01'),
],

每个页面只需要传入对应itemId就行,不需要额外写逻辑,批量替换成本极低

3.2 改造button.dart的状态同步

用ValueListenableBuilder监听状态变化,自动同步按钮颜色:

ValueListenableBuilder(
  valueListenable: favoriteManager.updateNotifier,
  builder: (context, _, child) {
    bool isFavorite = favoriteManager.getFavoriteStatus('0_01');
    return LearnLevelButton(
      color: isFavorite ? Colors.orange : const Color(0xff7ba6f9),
      text: '',
      onTap: () async {
        await Navigator.pushReplacement(context, MaterialPageRoute(builder: (context){
          return home0_01();
        }));
      },
    );
  }
)

所有修改完成后,收藏状态会自动持久化到本地,APP重启后也不会丢失,后续新增收藏条目不需要新增全局变量,直接传入对应itemId即可,扩展性很强

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 08:45:02