Flutter を使ったアプリ開発(APIでデータ取得とその表示)

IOS、Androidアプリを一括で開発するという要求に応えてくれるFlutter。

弊社ではこのFlutterを使用してスマホ対応のアプリ開発を行っています。

 

今回は、そんなFlutterを使用したアプリ開発、特にAPIでデータを取得し表示するところ(いわゆるget)の部分をご紹介していきます。

 

まずは、必要なライブラリーを入れていきます。

公式サイトはこちら

 

 

私の場合は、flutterへのパスを通していないので、展開先から呼び出します。

/Users/<USRNAME>/development/flutter/bin/flutter pub add http

pabspec.ymlに以下が追加されていれば成功です。

dependencies:
  flutter:
    sdk: flutter
  cupertino_icons: ^1.0.2
  http: ^0.13.3

次に、必要なモジュール群を読み込みます。

import 'package:flutter/material.dart'; 
import 'package:http/http.dart' as http; // API通信
import 'dart:async'; //非同期処理用
import 'dart:convert'; //httpレスポンスをJSON形式に変換用

 

そしたら後は書いていくだけです。今回はmain.dartに記述していきます。

まずは、お決まりの

void main() {
  // main.dartは基本これだけ
  runApp(MaterialApp(
    home: HomePage(),
  ));
}

ルーティングについては別箇所に記述する方法もありますが、今回はAPIを試すだけなので一旦これで。

 

class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}

void mainで呼ばれているHomePageクラスを定義しています。ここでは更に_HomePageStateを見にいくようにしました。

class _HomePageState extends State<HomePage> {
  late Map data;
  late List userData;

  Future getData() async {
    //Future xxx async{} という記法
    final response =
        await http.get(Uri.parse("<リクエストを投げるURL>"));
    final body = json.decode(response.body);
        // Unhandled Exception: type 'List<dynamic>' is not a subtype of type 'Map<dynamic, dynamic>' エラーに対処
    final articles = body.map((dynamic item) => item).toList();
    setState(() {
      userData = articles;
    });
  }

  // 非同期処理は、デフォルトでは呼び出し元は処理の完了を待ちませんが、
  // await キーワードをつけると完了を待つことができる。
  @override
  void initState() {
    super.initState();
    getData();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text("sample API"),
          backgroundColor: Colors.green,
        ),
        body: ListView.builder(
          //スクロール可能な可変リストを作る
          itemCount: userData == null ? 0 : userData.length, //受け取る数の定義
          itemBuilder: (BuildContext context, int index) {
            //ここに表示したい内容をindexに応じて表示させる
            return Card(
              //cardデザインを定義:material_design
              child: Row(
                children: <Widget>[
                  CircleAvatar(
                      child: Text(
// 今回はevent_nameとdate_and_timeを表示 ApI responseに応じて変換してください。
                    "${userData[index]["event_name"]} ${userData[index]["date_and_time"]}",
                    style: TextStyle(color: Colors.black),
                  )
                      )
                ],
              ),
            );
          },
        ));
  }
}

 

 

長くなってしまいましたが、こんな感じで進めていきます。

+++ 補足 +++

API開発をしていると、日本語が文字化けをするという問題が生じてしまうことがあります。

この問題を解決するためには、APIレスポンスを受け取る側(今回はFlutter側)で対応するケースと、API側(今回はDjangoのRestFrameWork)で対応するケースとがあります。

Flutter側で対応しようとすると毎度同じようなことでソースを書かないといけないので、API側で対応するのが良いかと思います。

ちなみに、DjangoのRestFrameWorkで日本語も文字化けが起こる時には、以下のように対応します。

from rest_framework.renderers import JSONRenderer

class UTF8CharsetJSONRenderer(JSONRenderer):
    charset = 'utf-8'

こんなファイルをアプリ側などにおき、

settings.pyに以下を追加あるいは変更します。

'DEFAULT_RENDERER_CLASSES': (
    '<YOUR APP PATH>.<上記のファイル名>.UTF8CharsetJSONRenderer',
)

 

これで日本語の文字化けもなく表示されるようになります。

 

 

今回は、FlutterからAPIで情報を取得する方法について書いていきました。

次回は、FlutterからAPI経由でPOSTするケースについて書いていこうと思います。

 

 

 

 

コメントを残す