TEXTBOOK SECTION / AI LEARNING

FlutterでAPIからデータを取得する

Flutterアプリケーション開発概論の「Flutter API連携入門|ポケモン図鑑アプリの作り方」より、FlutterでAPIからデータを取得するを解説。生成AI、AI活用、DX、業務改善を実践しながら学べるオンライン教材です。

8Flutter API連携入門|ポケモン図鑑アプリの作り方Flutter / iOS / Android / MacOS / Windows / 基礎から学ぶ / 開発 / アプリ開発

OVERVIEW

この節で学べること

概要を表示する
項目内容
教材名Flutterアプリケーション開発概論
Flutter API連携入門|ポケモン図鑑アプリの作り方
FlutterでAPIからデータを取得する
カテゴリFlutter / iOS / Android / MacOS / Windows / 基礎から学ぶ / 開発 / アプリ開発
学習内容生成AI、AI活用、DX、業務改善を実践しながら理解するための教材です。

TABLE OF CONTENTS

目次

CONTENT

ここから

前の節では、Flutterプロジェクトに http パッケージを追加しました。

ここから、いよいよFlutterアプリからPokeAPIへアクセスします。

この節では、まずAPIからデータを取得するところまでを作ります。

まだ、きれいなカードUIにはしません。

JSONを細かく整理する作業も、次の節で行います。

今回は、Flutterアプリが外部APIにアクセスして、データを受け取れる状態を作ることが目的です。


この節で作ること

今回作るのは、次のような流れです。

作業内容
APIのURLを用意するPokeAPIのポケモン取得URLを使う
http.get() を使うFlutterからAPIへリクエストを送る
レスポンスを確認する通信が成功したか確認する
取得結果を画面に表示する返ってきたJSON文字列を画面に出す

今回は例として、ピカチュウのデータを取得します。

https://pokeapi.co/api/v2/pokemon/25

忙しい方はここだけ見て

APIからデータを取得する基本形は、次のコードです。

/**
 * PokeAPIからポケモンデータを文字列として取得する関数。
 *
 * 入力: なし
 * 出力: APIから返ってきたJSON文字列
 */
Future<String> fetchPokemonData() async {
  final Uri url = Uri.https(
    'pokeapi.co',
    '/api/v2/pokemon/25',
  );

  final http.Response response = await http.get(url);

  if (response.statusCode != 200) {
    throw Exception('API通信に失敗しました');
  }

  return response.body;
}

この関数を呼び出すことで、FlutterアプリからPokeAPIのデータを取得できます。


API通信の基本イメージ

FlutterアプリからAPIを呼び出す流れは、とてもシンプルです。

Flutterアプリ
   ↓ リクエスト
PokeAPI
   ↓ レスポンス
JSONデータ

今回使う http.get() は、「このURLのデータをください」とお願いする処理です。

PokeAPIからは、ポケモンの名前、画像、タイプ、高さ、重さなどが入ったJSONデータが返ってきます。

ただし、この節ではJSONの中身を細かく整理しません。

まずは「取得できた」という感覚をつかみます。


手順1:main.dartを開く

lib/main.dart を開きます。

前の節で追加した、次のimportがあることを確認してください。

import 'package:http/http.dart' as http;

なければ追加します。

import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;

手順2:APIからデータを取得する関数を作る

まず、main.dart の中に次の関数を追加します。

/**
 * PokeAPIからピカチュウのデータを取得する関数。
 *
 * 入力: なし
 * 出力: APIから返ってきたJSON文字列
 */
Future<String> fetchPokemonData() async {
  final Uri url = Uri.https(
    'pokeapi.co',
    '/api/v2/pokemon/25',
  );

  final http.Response response = await http.get(url);

  if (response.statusCode != 200) {
    throw Exception('API通信に失敗しました');
  }

  return response.body;
}

ここで大事なのは、次の3つです。

コード意味
Uri.https()APIのURLを作る
await http.get(url)APIへアクセスする
response.bodyAPIから返ってきた中身を取り出す

response.body には、JSON形式の文字列が入っています。


asyncとawaitについて

API通信は、すぐに結果が返ってくるとは限りません。

インターネットを通して外部サーバーへアクセスするため、少し時間がかかります。

そこで使うのが、asyncawait です。

Future<String> fetchPokemonData() async {
  final http.Response response = await http.get(url);
  return response.body;
}

ざっくり言うと、次のような意味です。

書き方意味
Future<String>あとでStringが返ってくる
async時間のかかる処理を書く関数
await結果が返ってくるまで待つ

API通信では、この形をよく使います。


手順3:画面に表示する準備をする

今回は、ボタンを押したらAPI通信を行い、取得したJSON文字列を画面に表示します。

まず、状態を持てるように StatefulWidget を使います。

class PokemonHomePage extends StatefulWidget {
  const PokemonHomePage({super.key});

  @override
  State<PokemonHomePage> createState() => _PokemonHomePageState();
}

次に、状態管理用のクラスを作ります。

class _PokemonHomePageState extends State<PokemonHomePage> {
  String _pokemonData = 'まだデータを取得していません';

  /**
   * ボタンを押したときにPokeAPIからデータを取得する関数。
   *
   * 入力: なし
   * 出力: 画面に表示する文字列を更新する
   */
  Future<void> _loadPokemonData() async {
    final String result = await fetchPokemonData();

    setState(() {
      _pokemonData = result;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('ポケモン図鑑'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16),
        child: Column(
          children: <Widget>[
            ElevatedButton(
              onPressed: _loadPokemonData,
              child: const Text('APIからデータを取得する'),
            ),
            const SizedBox(height: 16),
            Expanded(
              child: SingleChildScrollView(
                child: Text(_pokemonData),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

これで、ボタンを押すとPokeAPIにアクセスし、返ってきたJSON文字列が画面に表示されます。


今回の完成コード

lib/main.dart を次のようにします。

import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;

/**
 * アプリの起点になる関数。
 *
 * 入力: なし
 * 出力: MyAppを起動する
 */
void main() {
  runApp(const MyApp());
}

/**
 * PokeAPIからピカチュウのデータを取得する関数。
 *
 * 入力: なし
 * 出力: APIから返ってきたJSON文字列
 */
Future<String> fetchPokemonData() async {
  final Uri url = Uri.https(
    'pokeapi.co',
    '/api/v2/pokemon/25',
  );

  final http.Response response = await http.get(url);

  if (response.statusCode != 200) {
    throw Exception('API通信に失敗しました');
  }

  return response.body;
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  /**
   * アプリ全体のUIを構築する関数。
   *
   * 入力: BuildContext
   * 出力: MaterialApp
   */
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'ポケモン図鑑',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.red),
        useMaterial3: true,
      ),
      home: const PokemonHomePage(),
    );
  }
}

class PokemonHomePage extends StatefulWidget {
  const PokemonHomePage({super.key});

  @override
  State<PokemonHomePage> createState() => _PokemonHomePageState();
}

class _PokemonHomePageState extends State<PokemonHomePage> {
  String _pokemonData = 'まだデータを取得していません';

  /**
   * PokeAPIからデータを取得し、画面表示用の文字列を更新する関数。
   *
   * 入力: なし
   * 出力: _pokemonDataを更新して画面を再描画する
   */
  Future<void> _loadPokemonData() async {
    final String result = await fetchPokemonData();

    setState(() {
      _pokemonData = result;
    });
  }

  /**
   * ポケモン図鑑のトップ画面を構築する関数。
   *
   * 入力: BuildContext
   * 出力: Scaffold
   */
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('ポケモン図鑑'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16),
        child: Column(
          children: <Widget>[
            ElevatedButton(
              onPressed: _loadPokemonData,
              child: const Text('APIからデータを取得する'),
            ),
            const SizedBox(height: 16),
            Expanded(
              child: SingleChildScrollView(
                child: Text(_pokemonData),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

実行して確認する

ターミナルでアプリを起動します。

flutter run

画面に次のボタンが表示されます。

APIからデータを取得する

ボタンを押して、長いJSON文字列が表示されれば成功です。

表示される内容の中には、次のような情報が含まれます。

"name":"pikachu"

この文字が見えたら、PokeAPIからピカチュウのデータを取得できています。


コードの流れを確認する

今回のコードは、次の順番で動いています。

1. ボタンを押す
2. _loadPokemonData() が呼ばれる
3. fetchPokemonData() が呼ばれる
4. http.get() でPokeAPIへアクセスする
5. response.body でJSON文字列を受け取る
6. setState() で画面を更新する
7. 取得したデータが画面に表示される

ポイントは、setState() です。

Flutterでは、画面に表示している値を変えたいときに setState() を使います。

setState(() {
  _pokemonData = result;
});

この処理によって、画面が更新されます。


よくあるエラー

1. httpが見つからない

次のようなエラーが出る場合があります。

Target of URI doesn't exist: 'package:http/http.dart'

この場合は、httpパッケージが追加されていません。

次のコマンドを実行します。

flutter pub add http

そのあと、もう一度実行します。

flutter pub get

2. Androidで通信できない

Androidエミュレーターで通信がうまくいかない場合、まずインターネットに接続されているか確認してください。

通常、HTTPS通信であればそのまま動くことが多いです。

今回のURLも https:// から始まっています。

https://pokeapi.co/api/v2/pokemon/25

それでも動かない場合は、エミュレーターを再起動してから、もう一度試します。


3. ボタンを押しても画面が変わらない

この場合は、setState() の中で _pokemonData を更新しているか確認します。

正しい例です。

setState(() {
  _pokemonData = result;
});

悪い例です。

_pokemonData = result;

このように setState() なしで値だけ変えても、画面が更新されないことがあります。


今回はまだやらないこと

この節では、APIからデータを取得するところまでを行いました。

ただし、次のことはまだ行いません。

まだやらないこと理由
JSONをMapに変換する次の節で扱う
ポケモン名だけを取り出すJSON変換後に行う
画像を表示する画像URLの取得後に行う
ローディング表示後の節で扱う
エラー表示の作り込み後の節で扱う

一気に作ろうとすると、どこでつまずいたのか分かりにくくなります。

まずは、APIからデータを取れる。

そこだけを、確実に押さえます。


確認問題

問1

FlutterからAPIへGETリクエストを送るときに使うコードはどれですか?

答え。

final http.Response response = await http.get(url);

問2

APIから返ってきた中身を取り出すには、どのプロパティを使いますか?

答え。

response.body

問3

通信が成功したかどうかを確認するために使う値は何ですか?

答え。

response.statusCode

問4

画面の表示内容を更新するときに使うFlutterの関数は何ですか?

答え。

setState()

まとめ

この節では、FlutterアプリからPokeAPIへアクセスし、APIデータを取得しました。

今回できるようになったことは、次の3つです。

できるようになったこと内容
APIのURLを作るUri.https() を使う
APIへアクセスするhttp.get() を使う
取得結果を画面に出すresponse.body をTextで表示する

この段階では、JSON文字列がそのまま表示されているため、まだ少し読みにくいです。

次の節では、このJSON文字列をFlutterで扱いやすい形に変換します。

つまり、Map に変換して、ポケモンの名前や画像URLなどを取り出せるようにしていきます。

FAQ

よくある質問

FlutterでAPIからデータを取得するは医療関係者向けだけの内容ですか。
医療分野の例が含まれる場合もありますが、医療関係者だけに限定した内容ではありません。生成AI、AI活用、DX、業務改善、プロトタイプ開発など、一般的なAI学習の事例として読める内容です。
AI初心者でも読めますか。
はい。AIをこれから学ぶ方、数学が苦手な方、仕事でAIを使いたい方にも読み進めやすいように、教材の章と節の流れに沿って整理しています。
サムネイル画像は必ず表示されますか。
はい。教材にcoverUrlが設定されている場合はその画像を表示し、未設定の場合は代替サムネイル画像を表示します。
Flutterアプリケーション開発概論のほかの章も読めますか。
はい。教材トップから章立てを確認でき、前後の節へもページ下部のナビゲーションから移動できます。