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("’", "'") .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("’", "'") .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à
相关产品推荐
相关产品推荐

