Flutter中能否获取多个RSS Feed?求实现方案
多RSS链接接入实现方案
完全可以实现多RSS链接接入功能,以下是针对你现有代码的修改方案:
核心修改点
- 将单个RSS链接改为URI列表,支持添加多个源
- 批量加载所有RSS源,合并所有条目到统一列表
- 适配UI渲染逻辑,基于合并后的条目列表展示内容
修改后的完整代码
import 'package:webfeed/webfeed.dart'; import 'package:http/http.dart' as http; import 'package:url_launcher/url_launcher.dart'; import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; class Feed extends StatefulWidget { const Feed({Key? key}) : super(key: key); final String title = 'Últimas atualizações'; @override State<Feed> createState() => _FeedState(); } class _FeedState extends State<Feed> { // 定义多个RSS链接列表,可继续添加更多源 final List<Uri> feedUrls = [ Uri(scheme: 'https', host: 'rss.tecmundo.com.br', path: 'feed'), Uri.parse('https://nasa.gov/rss/dyn/lg_image_of_the_day.rss'), ]; List<RssItem> _allFeedItems = []; static const String placeholderImg = 'assets/images/noImage.jpg'; late GlobalKey<RefreshIndicatorState> _refreshKey; @override void initState() { super.initState(); _refreshKey = GlobalKey<RefreshIndicatorState>(); load(); } // 加载单个RSS源 Future<RssFeed?> loadSingleFeed(Uri url) async { try { final client = http.Client(); final response = await client.get(url); return RssFeed.parse(response.body); } catch (e) { debugPrint('加载RSS失败: $e'); } return null; } // 批量加载所有RSS源并合并条目 load() async { List<RssItem> tempItems = []; // 遍历所有RSS链接,逐个加载 for (var url in feedUrls) { final feed = await loadSingleFeed(url); if (feed?.items != null) { tempItems.addAll(feed!.items!); } } // 按发布时间倒序排序(可选) tempItems.sort((a, b) => b.pubDate?.compareTo(a.pubDate ?? DateTime.now()) ?? 0); setState(() { _allFeedItems = tempItems; }); // 所有源都加载失败时提示 if (_allFeedItems.isEmpty) { showDialog( context: context, builder: (BuildContext context) { return AlertDialog( title: const Text('加载失败'), content: const Text('所有RSS源均无法加载,请稍后重试'), actions: [ TextButton( child: const Text('确定'), onPressed: () => Navigator.pop(context), ), ], ); } ); } } Future<void> openFeed(String url) async { final Uri uri = Uri.parse(url); if (!await launchUrl(uri, mode: LaunchMode.inAppWebView)) { debugPrint('打开链接失败'); } } Text title(String? title) { return Text( title ?? '无标题', style: const TextStyle( fontSize: 18.0, fontWeight: FontWeight.w500, ), maxLines: 2, overflow: TextOverflow.ellipsis, ); } Text subtitle(String? subtitle) { return Text( subtitle ?? '无作者', style: const TextStyle( fontSize: 14.0, fontWeight: FontWeight.w100, ), maxLines: 1, overflow: TextOverflow.ellipsis, ); } Padding thumbnail(String? imageUrl) { return Padding( padding: const EdgeInsets.only(left: 15.0), child: imageUrl != null ? CachedNetworkImage( placeholder: (context, url) => Image.asset(placeholderImg), imageUrl: imageUrl, height: 50, width: 50, alignment: Alignment.center, fit: BoxFit.cover, ) : SizedBox( height: 50, width: 50, child: Image.asset(placeholderImg), ), ); } ListView list() { return ListView.builder( itemCount: _allFeedItems.length, itemBuilder: (BuildContext context, int index) { final item = _allFeedItems[index]; return ListTile( title: title(item.title), subtitle: subtitle(item.dc?.creator), leading: thumbnail(item.enclosure?.url), trailing: const Icon(Icons.bookmark_add_outlined), contentPadding: const EdgeInsets.all(5.0), onTap: () => openFeed(item.link ?? '') ); }, ); } bool isFeedEmpty() { return _allFeedItems.isEmpty; } Widget body() => isFeedEmpty() ? const Center(child: CircularProgressIndicator()) : RefreshIndicator( child: list(), onRefresh: () => load(), key: _refreshKey, ); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('最新更新'), ), body: body(), ); } }
额外优化建议
- 添加错误重试机制:对加载失败的单个RSS源可尝试重新加载
- 增加条目去重:通过链接或标题字段过滤不同源的重复内容
- 添加来源标签:给不同RSS源的条目添加标识,方便用户区分内容来源
内容的提问来源于stack exchange,提问作者Gustavo
相关产品推荐
相关产品推荐

