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

Flutter使用Provider本地保存收藏文章无效问题排查

你的Flutter收藏功能问题分析及修复方案

下面是代码中存在的关键问题和对应的修复方法:

1. 收藏/取消收藏逻辑完全颠倒

在ArticlePage的savedArticle方法中,判断逻辑搞反了:

// 错误代码
if (!isFavorite) {
  _favoriteArticles.removeFavorite(widget.id);
} else {
  _favoriteArticles.addFavorite(...);
}

修复:应该是当前未收藏时添加,已收藏时移除,同时更新本地状态:

if (!isFavorite) {
  _favoriteArticles.addFavorite(
    id: widget.id,
    urlImage: widget.urlImage,
    title: widget.title,
  );
  setState(() => this.isFavorite = true);
} else {
  _favoriteArticles.removeFavorite(widget.id);
  setState(() => this.isFavorite = false);
}

方法内重新获取_favoriteArticles是多余操作,直接用初始化好的实例即可。

2. 未加载本地存储的收藏数据

FavoriteArticles类中的loadFromSharedPreferences方法从未被调用,导致App启动后无法读取之前保存的收藏ID,收藏列表始终为空。

修复:在FavoriteArticles构造函数中异步加载本地数据:

class FavoriteArticles extends ChangeNotifier {
  FavoriteArticles() {
    Future.microtask(() => loadFromSharedPreferences());
  }
  // ... 其他代码不变
}

3. ArticlePage的ID参数不可靠

你把ArticlePage的id设为可选参数,但实际应该从widget.data中直接读取文章ID,避免widget.id为null导致收藏功能失效。

修复:删除冗余的可选参数,直接从data中提取数据:

class ArticlePage extends StatefulWidget {
  final Map<String, dynamic> data;
  const ArticlePage({Key? key, required this.data}) : super(key: key);

  @override
  _ArticlePageState createState() => _ArticlePageState();
}

class _ArticlePageState extends State<ArticlePage> {
  late FavoriteArticles _favoriteArticles;
  late bool isFavorite = false;

  @override
  void initState() {
    super.initState();
    _favoriteArticles = Provider.of<FavoriteArticles>(context, listen: false);
    final articleId = widget.data["id"] as int;
    isFavorite = _favoriteArticles.isFavorite(articleId);
  }

  Future<void> savedArticle() async {
    final articleId = widget.data["id"] as int;
    final currentIsFavorite = _favoriteArticles.isFavorite(articleId);

    if (!currentIsFavorite) {
      _favoriteArticles.addFavorite(
        id: articleId,
        urlImage: widget.data["_embedded"]["wp:featuredmedia"][0]["link"],
        title: widget.data["title"]["rendered"]
            .replaceAll("&#8217;", "'")
            .replaceAll("<p>", "")
            .replaceAll("</p>", ""),
      );
      setState(() => isFavorite = true);
    } else {
      _favoriteArticles.removeFavorite(articleId);
      setState(() => isFavorite = false);
    }
  }
}

4. ArticlePage中无效的removeFavorite方法

你写的removeFavorite方法逻辑完全错误,_favoriteArticleIds未初始化,也没有调用正确的Provider方法,直接删除该方法即可,收藏/取消逻辑已在savedArticle中处理。

5. 收藏页面展示逻辑错误

FavoritePage直接用data[index]匹配收藏ID对应的文章,会导致收藏ID和列表索引不匹配时展示错误内容。

修复:根据收藏ID从data中查找对应文章:

// 在FavoritePage的ListView.builder中修改itemBuilder
itemBuilder: (context, index) {
  final favoriteId = articleIds[index];
  final article = data.firstWhere(
    (item) => item["id"] == favoriteId,
    orElse: () => null,
  );

  if (article == null) return const SizedBox.shrink();

  return Card(
    margin: const EdgeInsets.all(8),
    elevation: 5,
    shadowColor: Colors.black26,
    color: Colors.white,
    child: InkWell(
      child: ClipRRect(
        borderRadius: BorderRadius.circular(10),
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            SizedBox(
              height: 190,
              width: double.infinity,
              child: Image(
                image: AdvancedNetworkImage(
                  article["_embedded"]['wp:featuredmedia'][0]["media_details"]["sizes"]["medium"]["source_url"],
                  useDiskCache: true,
                  cacheRule: const CacheRule(maxAge: Duration(days: 1)),
                ),
                fit: BoxFit.cover,
              ),
            ),
            Padding(
              padding: const EdgeInsets.only(left: 16, top: 16, bottom: 16),
              child: Row(
                children: [
                  Expanded(
                    child: Text(
                      article["title"]["rendered"]
                          .replaceAll("&#8217;", "'")
                          .replaceAll("<p>", "")
                          .replaceAll("</p>", ""),
                      style: const TextStyle(
                        fontSize: 18,
                        fontWeight: FontWeight.w600,
                        fontFamily: "Raleway",
                      ),
                      overflow: TextOverflow.ellipsis,
                      maxLines: 2,
                    ),
                  ),
                ],
              ),
            ),
          ],
        ),
      ),
      onTap: () {
        Navigator.push(context,
          MaterialPageRoute(
            builder: (context) => ArticlePage(data: article),
          ),
        );
      },
    ),
  );
},

6. ArticleModel无需混入ChangeNotifier

ArticleModel只是数据模型,不需要监听状态变化,移除多余的混入:

class ArticleModel { // 去掉with ChangeNotifier
  int? id;
  String? urlImage;
  String? urlImageSource;
  String? title;
  final String? description;
  String? link;
  bool isFavorite;

  // ... 其他代码不变
}

内容的提问来源于stack exchange,提问作者Pimpi Rimpà

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 17:57:04