バックエンドから API を取得し、取得した内容を画面に一覧表示します。

JSON データは、JSON Placeholder より photos(https://jsonplaceholder.typicode.com/)を使用します。

image2

まずは、flutter pub にある、httphttps://pub.dev/packages/http)をインストールします。

ターミナルで、dart pub add httpを実行します。

さらにターミナルで、flutter pub getを実行しましょう。

次に、httpで API と接続するためのヘルパーを作成します。

helpers フォルダを作成し、network_helper.dart を作成します。

まずは、http をインポートします。

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

NetworkHelper クラスを作成します。

url を取得できるようにしましょう。

class NetworkHelper {
  NetworkHelper({required this.url});

  final String url;
}

getData関数を非同期で作成します。

responseを設定します。

responseには、awaiturlからデータを取得できるよう設定します。

urlは、Uriで parse を設定します。

class NetworkHelper {
  NetworkHelper({required this.url});

  final String url;

  Future<dynamic> getData() async {
    http.Response response;

    response = await http.get(Uri.parse(url));

  }
}

responseのステータスコードが 200 の場合は、デーー他内容を取得します。

またデータは、デコードするために、jsonDecodeを使用します。

さらにconvertをインポートしましょう。

データを返します。

import 'dart:convert';

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

class NetworkHelper {
  NetworkHelper({required this.url});

  final String url;

  Future<dynamic> getData() async {
    http.Response response;

    response = await http.get(Uri.parse(url));

    if (response.statusCode == 200) {
      String data = response.body;
      dynamic jsonObjects = jsonDecode(data);
      return jsonObjects;
    }
  }
}

ステータスコードが 200 でない場合は、エラーが発生している場合なので、printでステータスコードが表示できるようにします。

if (response.statusCode == 200) {
  String data = response.body;
  dynamic jsonObjects = jsonDecode(data);
  return jsonObjects;
} else {
  print(response.statusCode);
}

ヘルパーの作成が完了したので、main.dart で一覧を取得できるようにします。

urlsを設定します。

class _MyHomePageState extends State<MyHomePage> {
  Future<List<String>>? urls;

getJsons 関数を非同期で作成します。

取得したデータを入れておく、配列を作成しましょう。

class _MyHomePageState extends State<MyHomePage> {
  Future<List<String>>? urls;
  Future<List<String>> getJsons() async {
    List<String> jsonUrls = [];
    }

取得したい JSON の url を設定します。

その url を、先程作成した networkHelper に設定し、データを取得します。

Future<List<String>> getJsons() async {
  List<String> jsonUrls = [];

  String url = "https://jsonplaceholder.typicode.com/photos";
  NetworkHelper networkHelper = NetworkHelper(url: url);

  List<dynamic> data = await networkHelper.getData();
}

print(data[1]);でデータが取得されているか確認すると、

image3

無事、API からデータを取得できていました。

例えば、print(data[1]["thumbnailUrl"]);で確認すると、

image4

指定した箇所の値を取得することができました。

こちらを利用し、JSON データの"thumbnailUrl"を取得しましょう。

class _MyHomePageState extends State<MyHomePage> {
Future<List<String>>? urls;
Future<List<String>> getJsons() async {
  List<String> jsonUrls = [];

  String url = "https://jsonplaceholder.typicode.com/photos";
  NetworkHelper networkHelper = NetworkHelper(url: url);

  List<dynamic> data = await networkHelper.getData();
  print(data[1]["thumbnailUrl"]);
  for (var i = 0; i < data.length; i++) {
    jsonUrls.add(data[i]["thumbnailUrl"]);
  }

  return jsonUrls;
}

次にinitStateurlsjsonUrlsを入れます。

@override
void initState() {
  urls = getJsons();
  super.initState();
}

FutureBuilderで非同期処理のビルドを作成します。

futureには、urlsを指定します。

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      title: Text(widget.title),
    ),
    body: SafeArea(
      child: Padding(
        padding: const EdgeInsets.all(8),
        child: FutureBuilder<List<String>>(
          future: urls,
        ),
      ),
    ),
  );
}

builderに、contextsnapshotを設定します。

さらに、API 取得中はローディングし、エラーが発生した場合はエラーメッセージを表示するようにします。

child: FutureBuilder<List<String>>(
  future: urls,
  builder: (BuildContext context, AsyncSnapshot snapshot) {
    if (snapshot.connectionState != ConnectionState.done) {
      return const Center(
        child: CircularProgressIndicator(),
      );
    }
    if (snapshot.hasError) {
      return Text(snapshot.error.toString());
    }
  },
),

データがあった場合には、データ一覧を表示し、データがなかった場合は、『データが存在しません』と表示するようにします。

Imageには、Image.networksnapshotdataを指定します。

child: FutureBuilder<List<String>>(
  future: urls,
  builder: (BuildContext context, AsyncSnapshot snapshot) {
    if (snapshot.connectionState != ConnectionState.done) {
      return const Center(
        child: CircularProgressIndicator(),
      );
    }
    if (snapshot.hasError) {
      return Text(snapshot.error.toString());
    }
    if (snapshot.hasData) {
      return GridView.builder(
        itemCount: 9,
        gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
            crossAxisCount: 3,
            crossAxisSpacing: 8.0,
            mainAxisSpacing: 8.0),
        itemBuilder: (context, index) {
          return Image.network(snapshot.data![index],
              fit: BoxFit.cover);
        },
      );
    } else {
      return const Text("データが存在しません");
    }
  },
),

では、動作確認しましょう。

image5

ローディングが表示され、

image6

API データの一覧内容を表示することができました。

ブログ一覧