最近の案件ではwebばかりで久々にモバイルアプリ開発をやりたくなった
とはいえ作りたいものがあるわけでもないので、勉強がてらQiita APIを使って適当なアプリを作っていく過程を記録する
少し前にswift/kotlinでそれぞれのOSの開発をやっていたがFlutterは今回初めて使います。
間違えとかあれば教えてください
repository:
環境準備
FlutterのSDKに関してはdocument通り。 flutter doctor
でエラーが出ないところまでやる。
久々にXcode落としたけど重いですね...
ひとまずflutterの準備は終わったのでアプリ作成
flutter create qiita_app
コマンドを打つだけ。難なく作成出来たので起動してみる
cd qiita_app
flutter run
macosかchromeで起動するか聞かれたのでとりあえずmacosを選び起動
macosのapplicationとして起動したっぽい
モバイルがやりたいのでiOSのsimulatorで起動したい
とりあえずsimulatorを起動
open -a Simulator
simulatorが起動したらもう一度アプリを起動してみる
今度は何で起動するか聞かれず自動的にiOSのsimulatorで起動した
Androidでも起動してみる
起動できるAVDのリストを出してみる
emulator -list-avds
emulator command not found
となってしまった。PATHの設定がされてなかったので~/Library/Android/sdk/emulator
をPATHに追加
もう一度実行
昔の案件で使っていたAVDが残ってたっぽいのでPixel_2_API_28
で起動してみる
emulator -avd Pixel_2_API_28
無事emulatorが起動したのでもう一度flutterアプリを起動
iOSのsimulatorを起動しっぱなしだったから選択肢が出てきたのでAndoridを選択して起動
無事両OS起動した
editorに関してVSCodeが推されてるっぽいので無難に使ってみる
こちらもFlutterのdocumentにあるセットアップをそのままやる
Qiita API叩いてみる
VSCodeを使うということでpluginのREST Clientを導入してみる
VSCodeのpluginで REST
って打つと多分一番上に出る
このpluginをinstallしqiita.http
ファイルを作成し以下を追加
GET https://qiita.com/api/v2/items?page=1&per_page=20
200応答が返ってきました。tokenをつけないとAPIのリクエスト制限が60req/hourみたいなので乱発の注意
実装
さあさあ準備が終わったので実装をしていく
とりあえずFlutterからこのAPIを実行してみたい。
とりあえず何も考えずlib/main.dart
にゴリゴリ書いていくことにする
Flutterのpackageにhttpなるものがあるので使わせていただく
flutter pub add http
pubspec.yaml
に差分が出た。恐らくpackage.json
みたいなものなのだろう
これでhttp
が使えるはず
READMEに書いてあるものをそのまま持ってきてgetArticles
関数を作ってみる
void getArticles() async {
var url = Uri.https('example.com', 'whatsit/create');
var response =
await http.post(url, body: {'name': 'doodle', 'color': 'blue'});
print('Response status: ${response.statusCode}');
print('Response body: ${response.body}');
print(await http.read(Uri.https('example.com', 'foobar.txt')));
}
これを元にqiitaのAPIを叩くよう変更してみる
query parameterはどう書けばいいのか
Uri.https
に飛んでみると丁寧にコメントが書いてあった
/// Example:
/// ```dart
/// var uri = Uri.https('example.org', '/path', {'q': 'dart'});
/// print(uri); // https://example.org/path?q=dart
なるほど、第3引数にオブジェクトで渡せば良さそう
void getArticles() async {
var url = Uri.https('qiita.com', 'api/v2/items', {'page': 1, 'per_page': 20});
var response = await http.get(url);
print('Response status: ${response.statusCode}');
print('Response body: ${response.body}');
}
こんな感じかな?この関数をボタンを押した際に呼び出してみる
ボタンを押した際の処理はどこにあるのかを探すと
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
),
このonPressed
で実行してる_incrementCounter
というのがそれっぽい
これを先ほど作ったgetArticles
に置き換えてみる
置き換えるとwarningが出ちゃったのでとりあえず何も考えず従う
最終的にこう
floatingActionButton: const FloatingActionButton(
onPressed: getArticles,
tooltip: 'Increment',
child: Icon(Icons.add),
)
起動して叩いてみるが、叩けてなさそう
[VERBOSE-2:dart_vm_initializer.cc(41)] Unhandled Exception: type 'int' is not a subtype of type 'Iterable<dynamic>'
#0 _Uri._makeQuery.<anonymous closure> (dart:core/uri.dart:2374:18)
#1 _LinkedHashMapMixin.forEach (dart:collection-patch/compact_hash.dart:625:13)
#2 _Uri._makeQuery (dart:core/uri.dart:2370:21)
#3 new _Uri (dart:core/uri.dart:1658:13)
#4 _Uri._makeHttpUri (dart:core/uri.dart:1797:12)
#5 new _Uri.https (dart:core/uri.dart:1693:12)
#6 getArticles (package:qiita_app/main.dart:9:17)
#7 _InkResponseState.handleTap (package:flutter/src/material/ink_well.dart:1096:21)
#8 GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:253:24)
#9 TapGestureRecognizer.handleTapUp (package:flutter/src/gestures/tap.dart:627:11)
#10 BaseTapGestureRecognizer._checkUp (package:flutter/src/gestures/tap.dart:306:5)
#11 BaseTapGestureRecognizer.acceptGesture (package:flutter/src/gestures/tap.dart:276:7)
#12 GestureArenaManager<…>
なんだろう。query parameterでintを使ったのがダメだったのか?
stringにしてもう一度叩いてみる
flutter: Response status: 200
flutter: Response body: [{"rendered_body":"\u003ch1 data-sourcepos=\"1:1-1:14\"\u003e\n\u003cspan id=\"はじめに\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E3%81%AF%E3%81%98%E3%82%81%E3%81%AB\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003eはじめに\u003c/h1\u003e\n\u003cp data-sourcepos=\"2:1-3:108\"\u003eRailsなどを中心に勉強中のエンジニア初心者が他の記事を参考にしたり、実際に実装してみたりして、アウトプットの一環としてまとめたものです。\u003cbr\u003e\n間違っていることもあると思われるので、その際は指摘いただけると幸いです。\u003c/p\u003e\n\u003ch1 data-sourcepos=\"5:1-5:7\"\u003e\n\u003cspan id=\"er図\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#er%E5%9B%B3\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003eER図\u003c/h1\u003e\n\u003cp data-sourcepos=\"7:1-7:85\"\u003eER図とは「DB上のテーブル同士の関連<…>
叩けた
長くなってしまったのでとりあえずここまで
次回はこのレスポンスを元に表示させてみたい