LoginSignup
4
4

More than 1 year has passed since last update.

FlutterでQiitaのアプリを作ってみる その1

Last updated at Posted at 2023-03-07

最近の案件ではwebばかりで久々にモバイルアプリ開発をやりたくなった
とはいえ作りたいものがあるわけでもないので、勉強がてらQiita APIを使って適当なアプリを作っていく過程を記録する

少し前にswift/kotlinでそれぞれのOSの開発をやっていたがFlutterは今回初めて使います。
間違えとかあれば教えてください

repository:

環境準備

FlutterのSDKに関してはdocument通り。 flutter doctor でエラーが出ないところまでやる。
image.png
久々に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に追加
もう一度実行
image.png
昔の案件で使っていたAVDが残ってたっぽいのでPixel_2_API_28で起動してみる

emulator -avd Pixel_2_API_28

無事emulatorが起動したのでもう一度flutterアプリを起動
image.png
iOSのsimulatorを起動しっぱなしだったから選択肢が出てきたのでAndoridを選択して起動

無事両OS起動した:tada:

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

image.png
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上のテーブル同士の関連<…>

叩けた:tada:
長くなってしまったのでとりあえずここまで
次回はこのレスポンスを元に表示させてみたい

4
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4