1. 概要
上記では、GraphQLClientを使ってGraphQLよりデータを取得する内容でした。今回は、モデルクラスの自動生成をやって同じ結果となる内容となります。
- ボイラープレートコードになりがちなコードを自動生成
対象としては開発を1年程やってて自分で最初から開発してみたい方になります。そのため細かい用語などの説明はしません。
2. nodeのインストール
こちらを参考
3. Back-End側のAPI開発
こちらを参考
4. DockerでMySQLを起動
5. Back-End側のサーバーを起動
6. プロジェクトの準備
6-1. プロジェクトを作成
7. 必要なライブラリをインストール
npm i graphql
npm i -D typescript @graphql-codegen/cli @graphql-codegen/flutter-freezed
8. GraphQL Code Generatorの設定ファイルを生成
8-1. codegen.ts
npx graphql-code-generator init
Welcome to GraphQL Code Generator!
Answer few questions and we will setup everything for you.
? What type of application are you building? Application built with other framework or vanilla JS
? Where is your schema?: (path or url) http://localhost:4000
? Pick plugins: TypeScript (required by other typescript plugins)
? Where to write the output: lib/data/models/app_models.dart
? Do you want to generate an introspection file? No
? How to name the config file? codegen.ts
? What script in package.json should run the codegen? codegen
Fetching latest versions of selected plugins...
Config file generated at codegen.ts
$ npm install
To install the plugins.
$ npm run codegen
To run GraphQL Code Generator.
- 上記コマンド実行で「codegen.ts」が生成される
- 「typescript」⇒「flutter-freezed」に修正
import type { CodegenConfig } from "@graphql-codegen/cli";
const config: CodegenConfig = {
overwrite: true,
schema: "http://localhost:4000",
generates: {
"lib/data/models/app_models.dart": {
plugins: ["flutter-freezed"],
},
},
};
export default config;
9. Dependenciesの追加
9-1. graphql_flutterやfreezedを追加
flutter pub add graphql_flutter freezed_annotation json_annotation
flutter pub add --dev build_runner freezed json_serializable
10. ソースコードの自動生成
10-1. graphql-codegenを実行
npm run codegen
- このコマンド実行で下記ファイルが生成される
- lib/data/models/app_models.dart
10-2. build_runnerを実行
flutter pub run build_runner build delete-conflicting-outputs
- このコマンド実行で下記2つのファイルが生成される
- lib/data/models/app_models.freezed.dart
- lib/data/models/app_models.g.dart
11. ソースコード
11-1. lib/data/models/*.dart
※自動生成ファイル
- app_models.dart
- app_models.freezed.dart
- app_models.g.dart
11-2. lib/ui/components/client.dart
import 'package:flutter/material.dart';
import 'package:graphql_flutter/graphql_flutter.dart';
const String host = 'localhost';
final HttpLink httpLink = HttpLink('http://$host:4000');
final ValueNotifier<GraphQLClient> client =
ValueNotifier(GraphQLClient(cache: GraphQLCache(), link: httpLink));
11-3. lib/ui/views/home.dart
import 'package:flutter/material.dart';
import 'package:graphql_codegen/data/models/app_models.dart';
import 'package:graphql_flutter/graphql_flutter.dart';
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
const String allUsers = r'''
query Users($published: Boolean!) {
users(published: $published) {
id
name
email
profile {
id
bio
userId
}
posts {
id
title
content
authorId
published
}
}
}
''';
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(widget.title),
),
body: Query(
options: QueryOptions(
document: gql(allUsers), variables: const {'published': false}),
builder: (QueryResult result,
{FetchMore? fetchMore, VoidCallback? refetch}) {
if (result.hasException) {
return Text('Error: ${result.exception.toString()}');
}
if (result.isLoading) {
return const CircularProgressIndicator();
}
if (result.data == null || result.data!.isEmpty) {
return const Text('No data');
}
final List<User> users = result.data!['users']
.map<User>((user) => User.fromJson(user))
.toList();
return ListView.builder(
itemCount: users.length,
itemBuilder: (context, index) => ListTile(
leading: const Icon(Icons.email),
title: Text(users[index].name!),
subtitle: Text(users[index].email),
));
}),
);
}
}
11-4. lib\main.dart
import 'package:flutter/material.dart';
import 'package:graphql_flutter/graphql_flutter.dart';
import 'package:graphql_codegen/ui/components/client.dart';
import 'package:graphql_codegen/ui/views/home.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return GraphQLProvider(
client: client,
child: CacheProvider(
child: MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const MyHomePage(title: 'Flutter - GraphQL with Codegen'),
),
),
);
}
}
12. 結果
13. 備考
Flutterでfreezedやgraphql-code-generatorでモデルクラスを自動生成しGraphQLClientを使ってGraphQLのAPIにアクセスし、データを取得する内容でした。
14. 参考
- Guide: Dart/Flutter – GraphQL Code Generator (the-guild.dev)
- flutter-freezed – GraphQL Code Generator (the-guild.dev)
投稿者プロフィール
-
開発好きなシステムエンジニアです。
卓球にハマってます。