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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 03:45:30