19. Flutterでwebfeedとhtmlを使ってRSSのリスト一覧を作成する
今回はFlutterでRSSの導入みたいなものを作成したいと思います。
RSSアプリの概要
今回RSSで使うXMLファイルはQiitaにユーザーフィードにしています。
ここで学習できた内容は
- ListViewとListTileの使い方
- 画面遷移
- ライブラリのインストール
- ウィジェットのイニシャライズ
こちらになります。
Flutterのライブラリのパッケージ
Flutterで使うパッケージは
- webfeed (RSSパーサーライブラリ)
- http (httpクライアント)
この2つを使って開発していきます。
それぞれのパッケージのインストールと使い方については上記ページの「Installing」タブに記載されています。
私のpubspec.yaml
は下記の通りです。
pubspec.yaml
dependencies: flutter: sdk: flutter # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^0.1.2 webfeed: ^0.4.2 http: ^0.12.0+4
RSSの構造はXMLをとってきてパースしてFeedのitemに変換しなければなりません。 XMLの取得についてはhttpを使って Feedの変換についてはwebfeedを使って それぞれ行います。
変換したitemをListTileのウィジェットに代入してそれをListViewにセットします。
サンプルコードについて
それではRSSアプリの基礎になるList一覧までのソースコードを書いていきます。
main.dart
import 'package:flutter/material.dart'; import 'package:rss_app/rss_list_page.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { // This widget is the root of your application. @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.green, ), home: RssListPage(), ); } }
import 'package:flutter/material.dart'; import 'package:rss_app/item_detail_page.dart'; import 'package:webfeed/webfeed.dart'; import 'package:http/http.dart'; class RssListPage extends StatefulWidget { final String title; final String url; RssListPage({@required this.title, @required this.url}); @override _RssListPageState createState() => _RssListPageState(title: title, url: url); } class _RssListPageState extends State<RssListPage> { final String _rssUrl = "https://qiita.com/tamappe/feed.atom"; final String title; final String url; List<Widget> _items = []; _RssListPageState({@required this.title, @required this.url}) { convertItemFromXML(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("RSS リーダー"), ), body: Center( child: ListView( padding: EdgeInsets.all(10.0), children: _items, ), ), ); } void convertItemFromXML() async { List<Widget> list = []; Response res = await get(_rssUrl); var atomFeed = new AtomFeed.parse(res.body); for (AtomItem item in atomFeed.items) { list.add(ListTile( contentPadding: EdgeInsets.all(10.0), title: Text( item.title, ), subtitle: Text( item.published ), onTap: () { Navigator.push(context, MaterialPageRoute( builder: (_) => ItemDetailPage( item: item, ) )); }, )); } setState(() { _items = list; }); } }
item_detail_page.dart
import 'package:flutter/material.dart'; import 'package:webfeed/webfeed.dart'; class ItemDetailPage extends StatefulWidget { final AtomItem item; ItemDetailPage({ @required this.item }); @override _ItemDetailPageState createState() => _ItemDetailPageState(item: item); } class _ItemDetailPageState extends State<ItemDetailPage> { AtomItem item; _ItemDetailPageState({@required this.item}); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(item.title), ), body: Center( child: Text(item.title) ), ); } }
これでビルドすると次のような動作になります。
自分のQiitaのフィードをもとにRSSアプリの基礎であるXMLファイルのパースが出来上がる。
— Tamappe@オンライン英会話のエンジニア (@tamapppe) 2020年2月16日
httpとwebfeedを使って実装する。 pic.twitter.com/ei1xEpRWgs
ツイッターでgifを貼り付けても自動再生されませんでした。。。
解説
それではhtmlとwebfeedの使い方について解説していきます。
今回ではRSSのURLをgetしてXMLファイルを取得するために使いました。
Response res = await get(_rssUrl);
get(url)でhttp通信を行うことができます。今回はGET
の通信を行いました。await
はDartにおける非同期処理を行うために使うものです。
await
を使うためにはメソッドにasync
が必要になるためメソッドにasync
を記載しています。
void convertItemFromXML() async {}
取得したresponseであるres
がFeedです。
公式でも次のように解説しています。
var atomFeed = new AtomFeed.parse(xmlString); // for parsing Atom feed
ちなみにQiitaのユーザーフィードはAtom仕様らしいのでAtomFeed
オブジェクトに変換しました。
RSS仕様の場合は次のとおりです。
var rssFeed = new RssFeed.parse(xmlString);
AtomFeedオブジェクトの取得に成功したらfor文を使ってそれぞれの記事のitemを取得しに行きます。
for (AtomItem item in atomFeed.items) { }
AtomItem
からItemの情報を取得する場合は
item.id item.title // 記事タイトル item.updated // 更新日 item.published // 投稿日
という感じになります。
そして、取得できた情報をListTileにセットしてListViewを表示させました。 これでRSSアプリの基本であるリスト一覧までが完成しました。
あとはまあ取得できたWEBのリンクを使ってウェブページを表示させるのが常套手段ですが、 今回はここまでにします。