[Flutter] API からデータを取得

概要

公式ドキュメントより、 API からデータを取得し画面表示する example を試す。

環境

  • Flutter 2.10.2
  • iPhone SE (2nd generation) シミュレータ
  • http: ^0.13.4

設計

今回の API

Json レスポンスを返すサービス「JSONPlaceholder」で行う。

crul で API Call した場合の結果がこちら。

$ curl https://jsonplaceholder.typicode.com/albums/1
{
  "userId": 1,
  "id": 1,
  "title": "quidem molestiae enim"
}

Flutter で API リクエスト

Dart 純正の http ライブラリを利用する。

http | Dart package
A composable, multi-platform, Future-based API for HTTP requests.

レスポンスの Json を任意のオブジェクトに変換

API レスポンスの Json を Flutter 内で扱いたい。

dart:convert を用いると任意のクラスに変換 ( convert ) できる。

dart:convert library - Dart API
dart:convert library API docs, for the Dart programming language.

チュートリアル

Flutter プロジェクト作成

Flutter プロジェクト作成。

flutter create test_http
cd test_http

http ライブラリ追加。

flutter pub add http

公式のサンプルプログラムを lib/main.dart に貼り付ける。内容としては

  • 「quidem molestiae enim」と表示

起動確認。

flutter run

API から取得したデータを表示できている。

MVVM パターンに分ける

Model・View・ViewModel を意識して機能を分けていく。
今回は試しに以下のようにした。

  • Model : Album 情報を保持する ( model.dart )
  • View : Album 情報を表示する UI ( view.dart )
  • ViewModel : Album 情報を取得し View 層に渡す ( view_model.dart )
  • 上記以外 : main.dart

main.dart

  • いつもの起動部分のみ
import 'package:flutter/material.dart';

import 'view.dart';

void main() => runApp(const MyApp());

view.dart

  • fetchAlbum() でデータを取得している
  • model 層を読み込んでいるのが気持ち悪い
import 'package:flutter/material.dart';

import 'view_model.dart';
import 'model.dart';

class MyApp extends StatefulWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  late Future<Album> futureAlbum;

  @override
  void initState() {
    super.initState();
    futureAlbum = fetchAlbum();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Fetch Data Example',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Fetch Data Example'),
        ),
        body: Center(
          child: FutureBuilder<Album>(
            future: futureAlbum,
            builder: (context, snapshot) {
              if (snapshot.hasData) {
                return Text(snapshot.data!.title);
              } else if (snapshot.hasError) {
                return Text('${snapshot.error}');
              }

              // By default, show a loading spinner.
              return const CircularProgressIndicator();
            },
          ),
        ),
      ),
    );
  }
}

view_model.dart

  • API Call の呼び出し
    • 非同期 ( async ) にするため Future クラスを利用
  • Model 層への入出力
import 'dart:async';
import 'dart:convert';

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

import 'model.dart';

Future<Album> fetchAlbum() async {
  final response = await http
      .get(Uri.parse('https://jsonplaceholder.typicode.com/albums/1'));

  if (response.statusCode == 200) {
    // If the server did return a 200 OK response,
    // then parse the JSON.
    return Album.fromJson(jsonDecode(response.body));
  } else {
    // If the server did not return a 200 OK response,
    // then throw an exception.
    throw Exception('Failed to load album');
  }
}

model.dart

  • Album 情報を保持
class Album {
  final int userId;
  final int id;
  final String title;

  const Album({
    required this.userId,
    required this.id,
    required this.title,
  });

  factory Album.fromJson(Map<String, dynamic> json) {
    return Album(
      userId: json['userId'],
      id: json['id'],
      title: json['title'],
    );
  }
}

まとめ

Flutter で API Call のやり方を学んだ。

適切なファイル分離が出来ておらず、気持ち悪い分け方となっている。
改善していきたい。

コードは Github にまとめた。

GitHub - runble1/flutter-fetch-sample
Contribute to runble1/flutter-fetch-sample development by creating an account on GitHub.

参考

Fetch data from the internet
How to fetch data over the internet using the http package.

複数情報を取得する場合はこちら。

FlutterでAPIリクエストを行う(初心者向け) - Qiita
最近ネイティブアプリに興味が湧いてきたのでFlutterを触りはじめました。今回はFlutterでAPIリクエストの実装例を紹介します。基本的に以下のドキュメントを読めば実装できるのですが、複数…

コメント

タイトルとURLをコピーしました