Flutter收藏功能问题:本地API与DB ID对比、点击无响应及列表展示
解决Flutter收藏功能核心问题:sqflite交互、状态同步与收藏列表展示
一、先实现sqflite数据库操作工具类
先封装一个数据库助手类,专门处理收藏ID的增删查操作(仅存ID即可,无需存储完整产品数据):
import 'package:sqflite/sqflite.dart'; import 'package:path/path.dart'; class FavoriteDatabaseHelper { static final FavoriteDatabaseHelper _instance = FavoriteDatabaseHelper._internal(); factory FavoriteDatabaseHelper() => _instance; FavoriteDatabaseHelper._internal(); static Database? _database; Future<Database> get database async { if (_database != null) return _database!; _database = await _initDatabase(); return _database!; } Future<Database> _initDatabase() async { String path = join(await getDatabasesPath(), 'favorites.db'); return await openDatabase( path, version: 1, onCreate: (db, version) async { await db.execute( 'CREATE TABLE favorites(id INTEGER PRIMARY KEY)', ); }, ); } // 添加收藏ID Future<void> addFavorite(int id) async { final db = await database; await db.insert('favorites', {'id': id}, conflictAlgorithm: ConflictAlgorithm.replace); } // 取消收藏 Future<void> removeFavorite(int id) async { final db = await database; await db.delete('favorites', where: 'id = ?', whereArgs: [id]); } // 获取所有已收藏ID Future<List<int>> getFavoriteIds() async { final db = await database; final List<Map<String, dynamic>> maps = await db.query('favorites'); return List.generate(maps.length, (i) => maps[i]['id'] as int); } }
二、修复FlowersScreen的收藏逻辑与状态同步
修改_FlowersScreenState,解决按钮无响应、硬编码ID、状态不同步的问题:
class _FlowersScreenState extends State<FlowersScreen> { List<ListAndDetailFlowerModelResponse> _products = []; final FavoriteDatabaseHelper _dbHelper = FavoriteDatabaseHelper(); List<int> _favoriteIds = []; @override void initState() { super.initState(); _loadFavoriteIds(); // 初始化时加载已收藏ID } // 加载已收藏ID并同步产品状态 Future<void> _loadFavoriteIds() async { _favoriteIds = await _dbHelper.getFavoriteIds(); if (_products.isNotEmpty) { setState(() { for (var product in _products) { product.isFavorite = _favoriteIds.contains(product.id); } }); } } // Code to get list flower Future<void> readListFlowerProduct() async { final String dataJsonFlower = await rootBundle .loadString('assets/json_file/list_and_detail_flower.json'); final productListFlower = json.decode(dataJsonFlower); var listFlower = productListFlower["productFLowers"] as List<dynamic>; setState(() { _products = listFlower .map((e) => ListAndDetailFlowerModelResponse.fromJson(e)) .toList(); // 同步已收藏状态 for (var product in _products) { product.isFavorite = _favoriteIds.contains(product.id); } }); } // End Code to get list flower // 处理收藏/取消收藏操作 Future<void> _toggleFavorite(ListAndDetailFlowerModelResponse product) async { setState(() { product.isFavorite = !product.isFavorite; }); if (product.isFavorite) { await _dbHelper.addFavorite(product.id); _favoriteIds.add(product.id); } else { await _dbHelper.removeFavorite(product.id); _favoriteIds.remove(product.id); } } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: const Color(0xFFFCECFA), body: Column( // ... 原有布局代码不变,仅修改收藏按钮部分 children: [ // ... 顶部标题、按钮代码不变 _products.isNotEmpty ? Expanded( child: Padding( padding: const EdgeInsets.only(left: 20, right: 20), child: GridView.builder( // ... 网格布局参数不变 itemBuilder: (context, index) { final product = _products[index]; return Card( // ... Card原有代码不变 child: Expanded( child: Column( // ... 图片、产品名称代码不变 children: [ // ... 图片部分不变 Padding( padding: const EdgeInsets.only( top: 3, bottom: 7, left: 22, right: 19), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( product.flowersName, style: FlowersNameCard().text4, ), GestureDetector( // 添加点击逻辑 onTap: () => _toggleFavorite(product), child: Icon( Icons.favorite, color: product.isFavorite ? Colors.red : Colors.white, ), ), ], ), ), ], ), ), ); }, ), ), ) : // ... 空状态代码不变 ], ), ); } }
三、实现收藏页面展示收藏列表
创建收藏页面,从数据库获取已收藏ID,再匹配JSON中的产品数据:
class FavoritesScreen extends StatefulWidget { const FavoritesScreen({super.key}); static const String routeName = '/favorites'; @override State<FavoritesScreen> createState() => _FavoritesScreenState(); } class _FavoritesScreenState extends State<FavoritesScreen> { final FavoriteDatabaseHelper _dbHelper = FavoriteDatabaseHelper(); List<ListAndDetailFlowerModelResponse> _favoriteProducts = []; @override void initState() { super.initState(); _loadFavoriteProducts(); } Future<void> _loadFavoriteProducts() async { // 1. 获取已收藏ID final favoriteIds = await _dbHelper.getFavoriteIds(); if (favoriteIds.isEmpty) { setState(() => _favoriteProducts = []); return; } // 2. 加载JSON产品列表 final String dataJsonFlower = await rootBundle .loadString('assets/json_file/list_and_detail_flower.json'); final productListFlower = json.decode(dataJsonFlower); var allProducts = productListFlower["productFLowers"] as List<dynamic>; var products = allProducts .map((e) => ListAndDetailFlowerModelResponse.fromJson(e)) .toList(); // 3. 筛选出已收藏的产品 setState(() { _favoriteProducts = products.where((p) => favoriteIds.contains(p.id)).toList(); }); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('我的收藏')), body: _favoriteProducts.isEmpty ? const Center(child: Text('暂无收藏')) : GridView.builder( padding: const EdgeInsets.all(20), gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 2, crossAxisSpacing: 30, mainAxisSpacing: 16, mainAxisExtent: 160, ), itemCount: _favoriteProducts.length, itemBuilder: (context, index) { final product = _favoriteProducts[index]; return Card( color: const Color(0xFFEAC0E6), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10), ), child: Column( children: [ Padding( padding: const EdgeInsets.only(top: 13), child: ClipRRect( borderRadius: BorderRadius.circular(10), child: Image.network( product.urlImage, width: 107, height: 102, fit: BoxFit.fill, ), ), ), Padding( padding: const EdgeInsets.only( top: 3, bottom: 7, left: 22, right: 19), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( product.flowersName, style: FlowersNameCard().text4, ), GestureDetector( onTap: () async { await _dbHelper.removeFavorite(product.id); _loadFavoriteProducts(); }, child: const Icon(Icons.favorite, color: Colors.red), ), ], ), ), ], ), ); }, ), ); } }
关键问题说明
- 收藏按钮无响应:原代码
onTap为空,现在添加_toggleFavorite方法,同步更新本地UI状态与数据库数据。 - 硬编码ID问题:原代码仅固定id=1的产品状态,现在通过
_favoriteIds列表对比所有产品ID,自动同步收藏状态。 - 收藏列表展示:通过数据库获取收藏ID后,筛选JSON中的产品数据,实现收藏页面的动态展示。
内容的提问来源于stack exchange,提问作者Ulfa Ladayya
相关产品推荐
相关产品推荐

