FlutterでGraphQLを使ってみた
モックがないので探してみた
REST APIだと、GraphQLが使えないので、ダミーのデータが用意されているサイトがないか探したら見つかりました!
そもそもGraphQLとREST APIの違いは?
GraphQLとRESTはどちらもAPIの設計パラダイムですが、彼らはいくつかの重要な点で異なります:
データ取得方法:
RESTでは、クライアントはサーバーにリソースの特定のURLを要求します。サーバーはフルレスポンスを返し、通常は必要以上の情報が含まれることがあります(これを「オーバーフェッチング」と言います)。クライアントがさらに詳細な情報を必要とする場合、追加のリクエストを送る必要があります(これを「アンダーフェッチング」と言います)。
一方、GraphQLでは、クライアントは必要なデータを指定するクエリをサーバーに送信します。サーバーはそれに基づいてレスポンスを作成し、クライアントが要求した正確なデータだけを返します。これにより、オーバーフェッチングとアンダーフェッチングの問題が解決します。
エンドポイント:
RESTでは、各リソース(ユーザー、投稿、コメントなど)に対して個別のエンドポイントが必要です。
一方、GraphQLでは、一般的には単一のエンドポイントがあります。これは、クライアントがサーバーから正確なデータを取得するために、データのクエリを指定するからです。
エラーハンドリング:
RESTでは、さまざまなHTTPステータスコード(200、404、500など)がエラー管理に使用されます。
一方、GraphQLでは、サーバーは常に200のステータスコードを返し、エラーはレスポンス本体の中で扱われます。
リアルタイムのデータ:
RESTでは、リアルタイムの更新を取得するために、クライアントはポーリング(定期的にサーバーにリクエストを送信する)を行うか、WebSocketsなどの別の技術を使用する必要があります。
一方、GraphQLはSubscriptionsという概念を持っており、これを使用すると、サーバーはクライアントにリアルタイムの更新をプッシュすることができます。
これらの違いは、どちらの技術が特定のプロジェクトや要件に最適かを決定する際に考慮すべき要点です。
ここで、クエリを実行してダミーのデータがどんなものか見ることができます。
FlutterでGraphQLを使用するには、こちらのパッケージを追加します。
こちらのソースコードを書いて実行する
import 'package:flutter/material.dart';
import 'package:graphql_flutter/graphql_flutter.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
Widget build(BuildContext context) {
final HttpLink link = HttpLink('https://rickandmortyapi.com/graphql');
// ValueNotifierとは、値が変更されたときに通知を受け取ることができるクラス
ValueNotifier<GraphQLClient> client = ValueNotifier(
GraphQLClient(
// GraphQLClientは、GraphQLのクエリを実行するためのクラス
cache: GraphQLCache(), // GraphQLCacheは、クエリの結果をキャッシュするためのクラス
link: link, // linkは、GraphQLのエンドポイントを指定するためのクラス
),
);
return GraphQLProvider(
// GraphQLProviderは、GraphQLのクエリを実行するためのクラス
client: client,
child: MaterialApp(
home: Home(),
),
);
}
}
class Home extends StatelessWidget {
// GraphQLのクエリ
final String query = """
query GetCharactersAndLocation {
characters(page: 2, filter: { name: "rick" }) {
info {
count
}
results {
name
}
}
location(id: 1) {
id
}
episodesByIds(ids: [1, 2]) {
id
}
}
""";
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('GraphQL Flutter Demo'),
),
body: Query(
// Queryは、GraphQLのクエリを実行するためのクラス
options: QueryOptions(
// QueryOptionsは、GraphQLのクエリを実行するためのクラス
document: gql(query), // gqlは、GraphQLのクエリを実行するためのクラス
),
// builderは、GraphQLのクエリの結果を表示するためのウィジェット
builder: (QueryResult result,
{VoidCallback? refetch, FetchMore? fetchMore}) {
if (result.hasException) {
return Text(result.exception.toString()); // クエリの実行に失敗した場合
}
if (result.isLoading) {
// クエリの実行中の場合
return Text('Loading');
}
// クエリの実行に成功した場合
List characters = result.data?['characters']['results'];
String locationId = result.data?['location']['id'];
List episodes = result.data?['episodesByIds'];
return ListView.builder(
itemCount: characters.length, // クエリの結果の件数
itemBuilder: (context, index) {
final character = characters[index]; // クエリの結果のデータ
return ListTile(
title: Text(character['name']), // クエリの結果のデータのname
subtitle:
Text('Location ID: $locationId'), // クエリの結果のデータのlocationのid
);
},
);
},
),
);
}
}
まとめ
httpを使った時のように、APIからデータを取得することができたのですが、いつものようにGETしたわけではありません。
GraphQLはHTTPのGETやPOSTリクエストを使用できますが、それらを使用する方法はRESTとは異なります。
RESTでは、HTTPのGETメソッドはデータの取得、POSTメソッドはデータの作成、PUTメソッドはデータの更新、DELETEメソッドはデータの削除に使用されます。これはHTTPメソッドのセマンティクスに基づいています。
一方、GraphQLでは、クエリ(データの取得)とミューテーション(データの作成、更新、削除)という2つの種類の操作があります。これらの操作はどちらもGETまたはPOSTリクエストを介して実行できます。
HTTPのGETメソッドを使用する場合、GraphQLのクエリはURLのクエリパラメータとして送信されます。この方法は主にデータの取得に使われ、ブラウザのURLから直接GraphQLのクエリを実行することができます。
HTTPのPOSTメソッドを使用する場合、GraphQLのクエリまたはミューテーションはリクエストのボディに含まれ、一般にJSON形式で送信されます。これはデータの取得だけでなく、データの作成、更新、削除にも使われます。
したがって、GraphQLは確かにHTTP GETを使うことができますが、その使用方法はRESTとは異なります。
Discussion