はじめに
どうも。株式会社implのkashimaです。
ここ1ヶ月ほどでFlutterを触る機会が少しずつ増えてきまして、学習整理のため簡単に記事にしてみたいと思います。
前提
Flutterの環境構築が終わっていることが前提です。念の為載せておきます。
公式よりこちらの方がぶっちゃけわかりやすかったのでこちらのリンクを貼っておきます。
プロジェクト作成
まずはターミナルの任意のディレクトリから自由な名前でプロジェクトを作成します。
flutter create connectapi
プロジェクトのディレクトリを開き、適当なiOSのシミュレータを立ち上げた上でVSコード左のデバッグボタンを押すとiOSのシミュレータが立ち上がって初期画面が表示されると思います。
これで下準備は完了です。
実装する
初期コードのリファクタリング
- main.dartのコメントアウトを全て消します。
- libディレクトリ配下に別ファイルを作成し、MyHomePage以降を別ファイルに移動します。home.dartとか適当な名前でOKです。
lib/main.dart
import 'package:connectapi/home.dart';
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return const MaterialApp(
title: 'Flutter Sample',
home: MyHomePage(title: 'Flutter Sample'),
);
}
}
lib/home.dart
import 'package:flutter/material.dart';
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headlineMedium,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}
}
APIを取得するための関数を作成する
使用するAPI
今回使用するAPIはこちらです。
ランダムでyesかnoの返答と何かしらの画像が出てくる謎APIです。
リクエストを送るための非同期処理
リクエストを送るのに必要なHTTPパッケージをターミナルからインストールします。
flutter pub add http
Futureで非同期処理にして、データを更新、描画するようにしてみます。
非同期処理とは時間のかかるような処理を実行中でも別の処理を行うことができる処理の方法です。
パスタを茹でてる間に野菜と肉を切っとくみたいなイメージです。
dynamic responseState;
Future<void> getData() async {
final response = await http.get(Uri.https('yesno.wtf', '/api'));
final jsonResponse = jsonDecode(response.body);
setState(() {
responseState = jsonResponse;
});
}
上のコードをざっくり説明すると
- responseStateというdynamic型の変数を用意しておく(こいつに最終的にデータが入ってくる)
- http.getというメソッドでAPIのエンドポイントを叩く -> final response
- レスポンスをJSON型に変換する -> final jsonResponse
- setStateでデータを更新する
今こんな感じ
いったんエラー無視で進めます。
lib/home.dart
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http; // HTTPリクエスト用パッケージ
import 'dart:convert'; // JSONへの変換用パッケージ
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
dynamic responseState;
Future<void> getData() async {
final response = await http.get(Uri.https('yesno.wtf', '/api'));
final jsonResponse = jsonDecode(response.body);
setState(() {
responseState = jsonResponse;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headlineMedium,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}
}
実際に画面に表示する
Columnウィジェット内にウィジェットを追加し、実際に画面に表示してみましょう
responseStateの中に入ってきたデータを表示するためにText , Image , ElevatedButtonを追加します。
lib/home.dart
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http; // HTTPリクエスト用パッケージ
import 'dart:convert'; // JSONへの変換用パッケージ
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
dynamic responseState;
Future<void> getData() async {
final response = await http.get(Uri.https('yesno.wtf', '/api'));
final jsonResponse = jsonDecode(response.body);
setState(() {
responseState = jsonResponse;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Flutter Sample'),
),
body: Center(
child: Column(
children: [
Text(
responseState == null ? 'Yes or No' : responseState['answer'],
style: const TextStyle(fontSize: 30),
),
SizedBox(
width: 250,
height: 250,
child: Image.network(responseState == null
? 'https://yesno.wtf/assets/yes/11-a23cbde4ae018bbda812d2d8b2b8fc6c.gif'
: responseState['image']),
),
ElevatedButton(
onPressed: getData,
child: const Text('APIを叩くよ'),
)
],
),
),
);
}
}
responseStateの初期値がnullの状態になっているので初期値を適当に設定し、ElevatedButtonを押下すると、レスポンスがTextとImageに表示されるようになると思います。
動作確認
最後に
まだまだdartとflutterの記法に慣れませんね。。
Null Safetyを活かしてもっと綺麗な書き方ができるように勉強しときます。