Flutter中使用shared_preferences实现大量收藏按钮本地存储的方案咨询
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
相关产品推荐
相关产品推荐

