前回の続き。
-
FlutterでTwitterクライアント作成②フッター追加
前回、FlutterでTwitterのクライアントアプリを作ろうということでヘッダーを追加したところまでやりました。 今回はフッターを追加して画面を切り替えられるようにしたいと思います。 目次1 フッ ...
続きを見る
今回はホーム画面にTwitterのタイムライン情報を読み込んでみます。
目次
まずはお試し
いきなりTwitter APIだと難しそうなので、もっと簡単なやつで情報取得できるかを確認します。
こちらを参考にしました。
http通信を使えるようにする
pubspec.yamlのdependenciesにhttpを追加します。
1 2 3 4 5 6 7 8 |
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 http: any # 追加する |
http通信して情報を表示する
home_route.dartでAPIに接続して情報を取得します。
FlutterリポジトリのIssuesの一覧だそうです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; import '../header.dart'; class Home extends StatefulWidget { @override _Home createState() => _Home(); } class _Home extends State<Home> { final String screenName = 'ホーム'; String _timelineData = ''; @override void initState() { super.initState(); _load(); } Future<void> _load() async { final res = await http.get('https://api.github.com/repositories/31792824/issues'); setState(() { _timelineData = res.body; }); } @override Widget build(BuildContext context) { return Scaffold( appBar: Header(headerTitle: screenName), body: Center(child: Text(_timelineData)), ); } } |
パッケージの追加
httpを追加します。
as httpとしている理由は
httpパッケージにはgetやpostといった単純な名前があり、他の識別子との衝突を避けたい場合などにこの機能を使います。
とのこと。
1 2 3 |
import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; // 追加してhttpという名前を付ける import '../header.dart'; |
HomeをStatefulWidgetに変更
StatelessWidgetだと取得したデータを描画できないので、StatefulWidgetに変更します。
httpで取得したデータ用に変数を追加してます。
1 2 3 4 5 6 7 8 |
class Home extends StatefulWidget { @override _Home createState() => _Home(); } class _Home extends State<Home> { final String screenName = 'ホーム'; String _data = ''; |
httpで情報を取得
initState()は前回やった通り、画面描画前に走る処理です。
画面を表示する前にGitHubから情報を取得する処理を実行しています。
_load()はHTTP通信でデータを取得する処理です。
通常、APIを叩くときは非同期処理を行います。
- asyncを付けることで非同期メソッドにする
- http.getで非同期通信を行い、Futureを返す
- awaitを付けてデータが返ってくるのを待ち受ける
FutureはJavaScriptでいうPromiseのようなものとのこと。
この仕組みがあるため、データが返ってくるのを待たずに次の処理に進んでいます。
1 2 3 4 5 6 7 8 9 10 11 12 |
@override void initState() { super.initState(); _load(); } Future<void> _load() async { final res = await http.get('https://api.github.com/repositories/31792824/issues'); setState(() { _data = res.body; }); } |
取得したデータを表示
bodyには_dataを取得しています。
非同期処理をしているため先に画面描画処理が行われ、setStateで_dataが更新され次第表示されます。
1 2 3 4 5 6 7 |
@override Widget build(BuildContext context) { return Scaffold( appBar: Header(headerTitle: screenName), body: Center(child: Text(_data)), // http通信で取得したデータを指定 ); } |
パーミッションの追加
権限の設定をしておかないと、リリースビルド時に失敗します。
AndroidのAndroidManifest.xmlに追記します。
1 2 3 |
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.twitter_client"> <uses-permission android:name="android.permission.INTERNET" /> <!-- 追加 --> |
iOS用も何か追加しないといけない気がするけど、今回はAndroidしか動かさないので割愛。
main.dartを修正
今の状態でHot Restartするとエラーが出ました。。。
Headerでエラーを吐いてます。
1 2 3 4 5 6 7 8 9 10 |
When the exception was thrown, this was the stack #2 new Text package:flutter/…/widgets/text.dart:285 #3 Header.build package:twitter_client/header.dart:18 #4 StatelessElement.build package:flutter/…/widgets/framework.dart:4291 #5 ComponentElement.performRebuild package:flutter/…/widgets/framework.dart:4223 #6 Element.rebuild |
調べたところ、main.dartとhome_route.dartでそれぞれヘッダーを描画しようとしてるのがダメみたい。
ということで、以下を削除します。
1 2 3 4 5 6 7 8 9 10 11 12 |
// import 'header.dart'; Widget build(BuildContext context) { return MaterialApp( theme: ThemeData( primaryColor: Colors.pink[100], ), home: Scaffold( // appBar: Header(), // body: Center(child: Text('ホーム')), bottomNavigationBar: RootWidget(), ), ); |
これで改めてHot Restartすると…。
取得した生データが表示されました。
画面を切り替えると再取得しています。
これでAPIを叩いて情報を取得する処理のベースができました。
Twitter API Keyの取得
Twitterのタイムライン他の情報を取得するには公開されているAPIを使用します。
このAPI、以前は割と自由に使えたんですが、2018年に取得が厳しくなってました。。。
とはいえ一般人でも取得は可能です。
取得方法は時々変わるみたいなので、最新の情報をもとにAPI Keyを取得してください。
新しめのはこちら。
Twitter タイムライン情報を取得する
API keyが取得出来たらタイムラインの情報を取得してみます。
公式リファレンスはこちら。
認証用ライブラリを追加する
Twitterの認証は自分で実装することもできますが、Dart用のライブラリがあったのでそちらを使用することにしました。
(結局http使わなかった)
pubspec.yamlに以下を追加します。
1 2 3 4 5 6 7 8 9 |
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 http: any twitter_1user: ^1.0.1 // 追加する |
タイムラインの情報を取得する
home_route.dartを修正してTwitterのAPIに接続します。
_loadの中身を以下のように書き換えます。
API Keyなどは各自取得してください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
import 'package:twitter_1user/twitter_1user.dart'; // import 'package:http/http.dart' as http; Future<void> _load() async { final String apiKey = 'Twitter Developerで取得したAPI Key'; final String apiSecret = 'Twitter Developerで取得したAPI secret key'; final String accessToken = 'Twitter Developerで取得したAccess token'; final String accessSecret = 'Twitter Developerで取得したAccess token secret'; final String userTimelinePath = 'statuses/home_timeline.json'; Twitter twitter = new Twitter(apiKey, apiSecret, accessToken, accessSecret); final res = await twitter.request('GET', userTimelinePath, {'count': '30'}); setState(() { _timelineData = res; }); } |
これを保存した結果がこちら。
何が書いてあるかわかりませんが、twimgなどなんとなくTwitterっぽい文字列が確認できます。
取得した情報をdecodeする
今のままだと何が返ってきているのかよくわからないので、日本語に直してみます。
home_route.dartの_loadにjsonDecodeを追加します。
convertのimportも必要。
_timelineDataはStringじゃないといけないので、textのみを拾って出力します。
1 2 3 4 5 6 7 8 |
import 'dart:convert'; ・・・ final res = jsonDecode(await twitter.request('GET', userTimelinePath, {'count': '30'})); setState(() { for (int i = 0; i < res.length; i++){ _timelineData += res[i]['text'] + '\n'; // textだけ取得 } }); |
これを保存して情報を取り直すとこう。
tweetのテキスト部分だけが表示されました。
ちなみに、home_timeline.jsonはこれだけの情報を持ってます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
{ "created_at": "Wed Oct 10 20:19:24 +0000 2018", "id": 1050118621198921728, "id_str": "1050118621198921728", "text": "To make room for more expression, we will now count all emojis as equal—including those with gender and skin t… https://t.co/MkGjXf9aXm", "truncated": true, "entities": { "hashtags": [], "symbols": [], "user_mentions": [], "urls": [ { "url": "https://t.co/MkGjXf9aXm", "expanded_url": "https://twitter.com/i/web/status/1050118621198921728", "display_url": "twitter.com/i/web/status/1…", "indices": [ 117, 140 ] } ] }, "source": "<a href="http://twitter.com" rel="nofollow">Twitter Web Client</a>", "in_reply_to_status_id": null, "in_reply_to_status_id_str": null, "in_reply_to_user_id": null, "in_reply_to_user_id_str": null, "in_reply_to_screen_name": null, "user": { "id": 6253282, "id_str": "6253282", "name": "Twitter API", "screen_name": "TwitterAPI", "location": "San Francisco, CA", "description": "The Real Twitter API. Tweets about API changes, service issues and our Developer Platform. Don't get an answer? It's on my website.", "url": "https://t.co/8IkCzCDr19", "entities": { "url": { "urls": [ { "url": "https://t.co/8IkCzCDr19", "expanded_url": "https://developer.twitter.com", "display_url": "developer.twitter.com", "indices": [ 0, 23 ] } ] }, "description": { "urls": [] } }, "protected": false, "followers_count": 6128663, "friends_count": 12, "listed_count": 12900, "created_at": "Wed May 23 06:01:13 +0000 2007", "favourites_count": 32, "utc_offset": null, "time_zone": null, "geo_enabled": null, "verified": true, "statuses_count": 3659, "lang": "null", "contributors_enabled": null, "is_translator": null, "is_translation_enabled": null, "profile_background_color": "null", "profile_background_image_url": "null", "profile_background_image_url_https": "null", "profile_background_tile": nulll, "profile_image_url": "null", "profile_image_url_https": "https://pbs.twimg.com/profile_images/942858479592554497/BbazLO9L_normal.jpg", "profile_banner_url": "https://pbs.twimg.com/profile_banners/6253282/1497491515", "profile_link_color": "null", "profile_sidebar_border_color": "null", "profile_sidebar_fill_color": "null", "profile_text_color": "null", "profile_use_background_image": null, "has_extended_profile": null, "default_profile": false, "default_profile_image": false, "following": nul, "follow_request_sent": null, "notifications": null, "translator_type": "null" }, "geo": null, "coordinates": null, "place": null, "contributors": null, "is_quote_status": false, "retweet_count": 161, "favorite_count": 296, "favorited": false, "retweeted": false, "possibly_sensitive": false, "possibly_sensitive_appealable": false, "lang": "en" } |
タイムラインは文字だけじゃないので…
とりあえずtweetのテキストはできるようになりましたが、まだまだタイムラインとは程遠いですね。
やっぱりユーザーアイコン、ユーザー名、返信ボタンなども表示しないと。
ということで、次回はタイムラインっぽい見た目にします。
-
FlutterでTwitterクライアント作成④タイムラインをListTileで装飾
前回の続き。 今回はタイムラインの表示をTwitterっぽくします。 目次1 Flutter標準のUIを使用する1.1 tweetをリスト形式で表示する1.1.1 LinkedHashMapの追加1. ...
続きを見る
ここまでのコードはGitHubで。