I am trying to set up an RSS feed for my application, so it would be interesting to put several different RSS links into it. However, I've already tried several ways to execute this task, like putting various links directly in a List, and each time I failed and couldn't find a solution anywhere.
So the big question is: is it possible to do this?
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';
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> {
static Uri feedUrl = Uri(
/* 'https://nasa.gov/rss/dyn/lg_image_of_the_day.rss' */
scheme: 'https',
host: 'rss.tecmundo.com.br',
path: 'feed'
);
RssFeed _feed = RssFeed(link: 'https://rss.tecmundo.com.br/feed');
static const String placeholderImg = 'assets/images/noImage.jpg';
late GlobalKey<RefreshIndicatorState> _refreshKey;
@override
void initState() {
super.initState();
_refreshKey = GlobalKey<RefreshIndicatorState>();
load();
}
// GETTING THE FEED
Future<RssFeed?> loadFeed() async {
try {
final client = http.Client();
final response = await client.get(feedUrl);
return RssFeed.parse(response.body);
} catch (e) {
//
}
return null;
}
load() async {
loadFeed().then((result) {
if (null == result || result.toString().isEmpty) {
return showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: const Text('Erro ao carregar.'),
content: const Text('Tente novamente mais tarde.'),
actions: [
TextButton(
child: const Text('OK'),
onPressed: () {
Navigator.pop(context);
},
),
],
);
}
);
}
updateFeed(result);
});
}
updateFeed(feed) {
setState(() {
_feed = feed;
});
}
Future<void> openFeed (String url) async {
final Uri uri = Uri.parse(url);
if(!await launchUrl(uri, mode: LaunchMode.inAppWebView)) {
print('Error');
}
}
Text title (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 (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: _feed.items!.length,
itemBuilder: (BuildContext context, int index) {
final item = _feed.items![index];
return ListTile(
title: title(item.title),
subtitle: subtitle(item.dc?.creator),
leading: thumbnail(item.enclosure!.url),
trailing: Icon(Icons.bookmark_add_outlined),
contentPadding: const EdgeInsets.all(5.0),
onTap: () => openFeed(item.link ?? '')
);
},
);
}
bool isFeedEmpty () {
return null == _feed || null == _feed.items;
}
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('Latest updates'),
),
body: body(),
);
}
}```