😇
Ferry Graphql
公式の解説が親切ではない
FlutterでGraphQLを使うときに、ferryと呼ばれるライブラリを使うことがあるのだが、これは難しいと思った😅
だって公式に書いてあることわからないんだもん😇
ポケモンのAPIからデータをとってくるようだ???
実行すると長いログが表示される。
# This curl retrieves all items and relative costs
curl 'https://beta.pokeapi.co/graphql/v1beta' \
-H 'content-type: application/json' \
-H 'accept: */*' \
--compressed \
--data-binary @- << EOF
{
"query": "query getItems{pokemon_v2_item{name,cost}}",
"variables": null,
"operationName":"getItems"
}
EOF
完成品があるのでご興味ある方は試してみてください。
Flutter + Ferry GraphQL セットアップガイド
環境構築手順
- プロジェクトの作成
flutter create ferry_demo
cd ferry_demo
- 必要なパッケージの追加
flutter pub add \
ferry \
ferry_flutter \
gql_http_link \
built_collection \
built_value
flutter pub add --dev \
build_runner \
ferry_generator \
built_value_generator
- ファイル構造
lib/
├── graphql/
│ ├── schema.graphql # GraphQLスキーマ
│ └── queries/
│ └── get_items.graphql # クエリファイル
└── main.dart
- build.yamlの設定
targets:
$default:
builders:
ferry_generator|graphql_builder:
enabled: true
options:
schema: ferry_demo|lib/graphql/schema.graphql
ferry_generator|serializer_builder:
enabled: true
options:
schema: ferry_demo|lib/graphql/schema.graphql
GraphQLの実装例
- スキーマ定義 (
lib/graphql/schema.graphql
)
type Query {
pokemon_v2_item: [Item!]!
}
type Item {
name: String!
cost: Int!
}
- クエリの作成 (
lib/graphql/queries/get_items.graphql
)
query GetItems {
pokemon_v2_item {
name
cost
}
}
- コード生成
dart run build_runner build
lib/main.dart
)
使用例 (Client initClient() {
final httpLink = HttpLink('https://beta.pokeapi.co/graphql/v1beta');
final client = Client(link: httpLink);
return client;
}
// データの取得
Operation(
client: client,
operationRequest: GGetItemsReq((b) => b),
builder: (context, response, error) {
if (response == null || response.loading) {
return const CircularProgressIndicator();
}
final items = response.data?.pokemon_v2_item;
// データの表示
},
)
Ferryの特徴
- 型安全なGraphQLクライアント
- コード生成による型定義の自動生成
- IDEでのコード補完サポート
- Streamベースのリアクティブな実装
注意点
- スキーマファイルは正確に定義する必要がある
- コード生成は変更のたびに必要
- エンドポイントのURLは正確に指定する
このセットアップで、PokeAPIのGraphQLエンドポイントからデータを取得し、型安全な方法で表示することができます。
example
main.dart
の全体のコードです。
main.dart
import 'package:ferry/ferry.dart';
import 'package:ferry_demo/graphql/queries/__generated__/get_items.req.gql.dart';
import 'package:ferry_flutter/ferry_flutter.dart';
import 'package:flutter/material.dart';
import 'package:gql_http_link/gql_http_link.dart';
void main() {
final client = initClient();
runApp(MyApp(client: client));
}
Client initClient() {
final httpLink = HttpLink('https://beta.pokeapi.co/graphql/v1beta');
final client = Client(link: httpLink);
return client;
}
class MyApp extends StatelessWidget {
final Client client;
const MyApp({super.key, required this.client});
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(useMaterial3: true),
home: HomePage(client: client),
);
}
}
class HomePage extends StatelessWidget {
final Client client;
const HomePage({super.key, required this.client});
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.yellow, title: const Text('Pokemon Items')),
body: Operation(
client: client,
operationRequest: GGetItemsReq((b) => b),
builder: (context, response, error) {
if (response == null || response.loading) {
return const Center(child: CircularProgressIndicator());
}
if (response.hasErrors) {
return Center(
child: Text(response.graphqlErrors?.toString() ?? 'Error'));
}
final items = response.data?.pokemon_v2_item;
if (items == null) return const Center(child: Text('No items'));
return ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) {
final item = items[index];
return ListTile(
title: Text(item.name),
subtitle: Text('Cost: ${item.cost}'),
);
},
);
},
),
);
}
}
こんな感じで表示されました。これを使ってる人たちは仕事大変そーって思いました😅
REST APIの方が楽ですね。
Discussion