バックエンドから API を取得し、取得した内容を画面に一覧表示します。
JSON データは、JSON Placeholder より photos(https://jsonplaceholder.typicode.com/)を使用します。
まずは、flutter pub にある、http(https://pub.dev/packages/http)をインストールします。
ターミナルで、dart pub add httpを実行します。
さらにターミナルで、flutter pub getを実行しましょう。
次に、httpで API と接続するためのヘルパーを作成します。
helpers フォルダを作成し、network_helper.dart を作成します。
まずは、http をインポートします。
dart
import 'package:http/http.dart' as http;
NetworkHelper クラスを作成します。
url を取得できるようにしましょう。
dart
class NetworkHelper {
NetworkHelper({required this.url});
final String url;
}
getData関数を非同期で作成します。
responseを設定します。
responseには、awaitでurlからデータを取得できるよう設定します。
urlは、Uriで parse を設定します。
dart
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をインポートしましょう。
データを返します。
dart
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でステータスコードが表示できるようにします。
dart
if (response.statusCode == 200) {
String data = response.body;
dynamic jsonObjects = jsonDecode(data);
return jsonObjects;
} else {
print(response.statusCode);
}
ヘルパーの作成が完了したので、main.dart で一覧を取得できるようにします。
urlsを設定します。
dart
class _MyHomePageState extends State<MyHomePage> {
Future<List<String>>? urls;
getJsons 関数を非同期で作成します。
取得したデータを入れておく、配列を作成しましょう。
dart
class _MyHomePageState extends State<MyHomePage> {
Future<List<String>>? urls;
Future<List<String>> getJsons() async {
List<String> jsonUrls = [];
}
取得したい JSON の url を設定します。
その url を、先程作成した networkHelper に設定し、データを取得します。
dart
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]);でデータが取得されているか確認すると、
無事、API からデータを取得できていました。
例えば、print(data[1]["thumbnailUrl"]);で確認すると、
指定した箇所の値を取得することができました。
こちらを利用し、JSON データの"thumbnailUrl"を取得しましょう。
dart
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;
}
次にinitStateでurlsにjsonUrlsを入れます。
dart
@override
void initState() {
urls = getJsons();
super.initState();
}
FutureBuilderで非同期処理のビルドを作成します。
futureには、urlsを指定します。
dart
@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に、contextとsnapshotを設定します。
さらに、API 取得中はローディングし、エラーが発生した場合はエラーメッセージを表示するようにします。
dart
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.networkでsnapshotのdataを指定します。
dart
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("データが存在しません");
}
},
),
では、動作確認しましょう。
ローディングが表示され、
API データの一覧内容を表示することができました。