Flutter+SQLite收藏功能实现:根据收藏状态切换星标颜色
解决方案
1. 完善SQLite数据访问层(Dao)
在你的SQLite操作类中添加检查数据是否存在的方法,用唯一标识符(比如itemId)判断:
class FavoriteDao { final Database _db; FavoriteDao(this._db); // 检查指定ID的数据是否已收藏 Future<bool> isFavorite(int itemId) async { final result = await _db.query( 'favorites', where: 'id = ?', whereArgs: [itemId], ); return result.isNotEmpty; } // 已有的添加收藏方法 Future<void> addFavorite(ItemModel item) async { await _db.insert( 'favorites', item.toMap(), conflictAlgorithm: ConflictAlgorithm.replace, ); } // 已有的取消收藏方法 Future<void> removeFavorite(int itemId) async { await _db.delete( 'favorites', where: 'id = ?', whereArgs: [itemId], ); } // 获取所有已收藏的item ID列表 Future<List<int>> getFavoriteIds() async { final results = await _db.query('favorites'); return results.map((row) => row['id'] as int).toList(); } }
2. 数据模型补充必要方法
确保API数据模型有唯一ID,并实现转Map的方法用于数据库存储:
class ItemModel { final int id; final String title; final String content; ItemModel({required this.id, required this.title, required this.content}); // 转成数据库存储的Map格式 Map<String, dynamic> toMap() { return { 'id': id, 'title': title, 'content': content, }; } // 从数据库Map转模型(可选,用于读取本地数据) factory ItemModel.fromMap(Map<String, dynamic> map) { return ItemModel( id: map['id'], title: map['title'], content: map['content'], ); } }
3. 页面逻辑:关联API数据与本地收藏状态
在页面State类中维护API数据列表和已收藏ID列表,初始化时同步本地状态,点击星标时更新状态与数据库:
class ItemListPage extends StatefulWidget { const ItemListPage({super.key}); @override State<ItemListPage> createState() => _ItemListPageState(); } class _ItemListPageState extends State<ItemListPage> { late List<ItemModel> _apiItems = []; late List<int> _favoriteIds = []; bool _isLoading = true; // 假设你已初始化数据库实例 late FavoriteDao _favoriteDao; @override void initState() { super.initState(); _initData(); } Future<void> _initData() async { // 先获取本地已收藏的ID列表 _favoriteIds = await _favoriteDao.getFavoriteIds(); // 再请求API数据 _apiItems = await _fetchApiData(); setState(() { _isLoading = false; }); } // 替换为你的实际API请求逻辑 Future<List<ItemModel>> _fetchApiData() async { await Future.delayed(const Duration(seconds: 1)); return [ ItemModel(id: 1, title: '标题1', content: '内容1'), ItemModel(id: 2, title: '标题2', content: '内容2'), ItemModel(id: 3, title: '标题3', content: '内容3'), ]; } // 切换收藏状态 Future<void> _toggleFavorite(ItemModel item) async { final isFavorite = _favoriteIds.contains(item.id); // 先更新内存状态,立即刷新UI setState(() { isFavorite ? _favoriteIds.remove(item.id) : _favoriteIds.add(item.id); }); // 再异步操作数据库 isFavorite ? await _favoriteDao.removeFavorite(item.id) : await _favoriteDao.addFavorite(item); } @override Widget build(BuildContext context) { if (_isLoading) { return const Center(child: CircularProgressIndicator()); } return ListView.builder( itemCount: _apiItems.length, itemBuilder: (context, index) { final item = _apiItems[index]; final isFavorite = _favoriteIds.contains(item.id); return ListTile( title: Text(item.title), subtitle: Text(item.content), trailing: IconButton( icon: Icon( Icons.star, color: isFavorite ? Colors.yellow : Colors.grey, ), onPressed: () => _toggleFavorite(item), ), ); }, ); } }
核心逻辑说明
- 状态同步:用
_favoriteIds列表维护已收藏ID,避免每次判断都查询数据库,提升性能 - 初始化加载:先拉取本地收藏状态,再请求API数据,确保初始显示的星标状态正确
- 点击反馈:先更新内存状态刷新UI,再异步操作数据库,保证用户体验流畅
内容的提问来源于stack exchange,提问作者mark anthony
相关产品推荐
相关产品推荐

