Flutter GraphQL客户端插件brick_graphql的使用

Flutter GraphQL客户端插件brick_graphql的使用

Brisk GraphQL

Brick GraphQL 是用于与GraphQL服务器交互的核心逻辑库。

如何生成GraphQL数据

由于Brick与其他提供者(如SQLite)进行插值,必须有一个单一的数据生成点。该库选择从Dart生成代码(而不是像使用 Artemis 这样的GraphQL生成器),以便这些提供者的配置可以存在于相同的源文件中。

支持的Query配置

由于Dart是数据来源,它可能不会与GraphQL合同一一映射。Brick将智能地猜测要使用的操作并发送生成的变量。但是,可以通过 <code>Query(providerArgs)</code> 覆盖。

providerArgs
  • <code>'operation'</code> (GraphqlOperation) 应用此操作而不是从 <code>graphqlOperationTransformer</code> 中获取的默认操作。文档子字段不会由模型填充。
  • <code>'context'</code> (Map<String, ContextEntry>) 将此作为请求的上下文应用,而不是空对象。这对于后续消费者/Link很有用。键应为 <code>ContextEntry</code> 的运行时类型。
variablesNamespace

某些GraphQL系统可能利用单个变量属性来处理所有操作。默认情况下,Brick可以将所有请求中的所有变量包装在一个顶级键中:

// GraphqlProvider(variablesNamespace: 'vars')

query MyOperation($vars: MyInputClass!) {
  myOperation(vars: $vars) {}
}

💡 <code>GraphqlProviderQuery#variables</code> 将永远不会被 <code>variablesNamespace</code> 包装。

where

传递给 <code>where:</code> 的值会被转换为查询和订阅时发送的变量。自动填充的 <code>Query(where:)</code> 变量会被 <code>providerArgs: {'operation'}.variables</code> 覆盖,而不是混合。

Query(where: [
  Where('name').isExactly('Thomas')
])
// => {'name': 'Thomas'}

要扩展查询以包含自定义属性,可以使用 <code>GraphqlProvider#queryToVariables</code>

final query = Query.where('name', 'Thomas');
final variables = {
  ...graphqlProvider.queryToVariables(query),
  'myCustomVariable': true,
};

⚠️ <code>Where</code> 中的关联值不会被转换为变量。

toJson和子字段

当字段类型的类具有返回 <code>Map</code><code>#toJson</code> 方法时,子字段会根据该字段类型的 <code>final</code> 实例字段自动生成到请求中。

class Hat {
  final String fabric;
  final int width;

  Hat({this.fabric, this.width});

  Map<String, dynamic> toJson() => {'fabric': fabric, 'width': width};
}

class Mounty {
  final Hat hat;
  final String horseName;
  final String name;
}

这将在 <code>query</code><code>subscription</code> 中生成以下GraphQL文档:

query {
  myQueryName {
    hat {
      fabric
      width
    }
    horseName
    name
  }
}

模型

为了减少重复粘贴相同的GraphQL文档和变量,所有操作可以在一个地方设置,与模型配置一起。

  1. 创建一个扩展 <code>GraphqlQueryOperationTransformer</code> 的新类:

    class UserQueryOperationTransformer extends GraphqlQueryOperationTransformer {}
    
  2. 该类可以访问每个请求的 <code>query</code>,以及 <code>delete</code><code>upsert</code><code>instance</code>。你可以使用这些属性告诉Brick使用哪个GraphQL操作。

    class UserQueryOperationTransformer extends GraphqlQueryOperationTransformer {
      GraphqlOperation get upsert {
        if (query.where != null) {
          return GraphqlOperation(document: r'''
            mutation UpdateUserName($name: String!) {
              updateUserName(input: $input) {}
            }
          ''');
        }
        return GraphqlOperation(document: r'''
          mutation CreateUser($input: UserInput!) {
            createUser(input: $input) {}
          }
        ''');
      }
    }
    
  3. 在复杂情况下,如果整个模型没有被传输,也可以提供 <code>variables</code>

    class UserQueryOperationTransformer extends GraphqlQueryOperationTransformer {
      GraphqlOperation get upsert {
        if (query.where != null) {
          return GraphqlOperation(
            document: r'''
              mutation UpdateUserName($name: String!) {
                updateUserName(input: $input) {}
              }
            ''',
            variables: {'name': Where.firstByField('name', query.where)},
          );
        }
        return null;
      }
    }
    
  4. <code>GraphqlSerializable</code> 中使用该类:

    @GraphqlSerializable(
      queryOperationTransformer: UserQueryOperationTransformer.new
    )
    

💡 只需提供头部;节点可以用来覆盖模型请求的所有字段的默认行为。要使用由模型(与 <code>@Graphql</code> 配置相关)提供的自动填充节点,使用空节点选择(例如 <code>deleteUser(vars: $vars) {}</code>)。


示例代码

import 'package:brick_core/core.dart';
import 'package:brick_graphql/brick_graphql.dart';
import 'package:gql_http_link/gql_http_link.dart';

class UserQueryOperationTransformer extends GraphqlQueryOperationTransformer {
  GraphqlOperation get get => GraphqlOperation(document: '''
    query AllUsers {
      allUsers {}
    }
  ''');

  const UserQueryOperationTransformer(Query? query, GraphqlModel? instance)
      : super(query, instance);
}

/// 此类和代码始终由域生成
/// 例如使用 brick_offline_first_with_graphql_build 包
class UserAdapter extends GraphqlAdapter<User> {
  [@override](/user/override)
  final queryOperationTransformer = UserQueryOperationTransformer.new;

  [@override](/user/override)
  Map<String, RuntimeGraphqlDefinition> get fieldsToGraphqlRuntimeDefinition => {
        'name': const RuntimeGraphqlDefinition(
          association: false,
          documentNodeName: 'full_name',
          iterable: false,
          type: String,
        ),
      };

  [@override](/user/override)
  Future<User> fromGraphql(data, {required provider, repository}) async {
    return User(
      name: data['name'],
    );
  }

  [@override](/user/override)
  Future<Map<String, dynamic>> toGraphql(instance, {required provider, repository}) async {
    return {
      'name': instance.name,
    };
  }
}

/// 此值始终由域生成
/// 例如使用 brick_offline_first_with_graphql_build 包
final dictionary = GraphqlModelDictionary({
  User: UserAdapter(),
});

/// 模型是唯一的实现(例如一个Flutter应用)
class User extends GraphqlModel {
  final String name;

  User({
    required this.name,
  });
}

class MyRepository extends SingleProviderRepository<GraphqlModel> {
  MyRepository(String baseApiUrl)
      : super(
          GraphqlProvider(
            link: HttpLink(baseApiUrl),
            modelDictionary: dictionary,
          ),
        );
}

/// 运行在简单的Apollo GraphQL服务器上:
/*
const { ApolloServer } = require("apollo-server");

const typeDefs = gql`
  type User {
    name: String
  }
  type Query {
    allUsers: [User]
  }
`;

const user = { name: 'Thomas' };

const resolvers = {
  Query: {
    allUsers: () => [user],
  }
}
server.listen().then(({ url }) => {
  console.log(`🚀  Server ready at ${url}`);
});
*/
void main() async {
  final repository = MyRepository('http://localhost:4000');

  final users = await repository.get<User>();
  print(users);
}

更多关于Flutter GraphQL客户端插件brick_graphql的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter GraphQL客户端插件brick_graphql的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是一个关于如何在Flutter项目中使用brick_graphql插件的示例代码。brick_graphql是一个用于与GraphQL API进行交互的Flutter客户端库。这个示例将展示如何设置GraphQL客户端、执行查询以及处理响应。

1. 添加依赖

首先,在你的pubspec.yaml文件中添加brick_graphql依赖:

dependencies:
  flutter:
    sdk: flutter
  brick_graphql: ^x.y.z  # 替换为最新版本号

然后运行flutter pub get来获取依赖。

2. 配置GraphQL客户端

创建一个GraphQL客户端实例,并配置HTTP链接和缓存(如果需要)。

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

final HttpLink httpLink = HttpLink(
  uri: 'https://your-graphql-endpoint.com/graphql',
  client: http.Client(),
);

final ValueNotifier<GraphQLClient> client = ValueNotifier(
  GraphQLClient(
    link: httpLink,
    cache: InMemoryCache(),
  ),
);

3. 定义GraphQL查询

使用GraphQL查询语言(GQL)定义一个查询。例如,假设我们有一个获取用户信息的查询:

query GetUser($id: ID!) {
  user(id: $id) {
    id
    name
    email
  }
}

在Dart代码中,我们可以使用GQLExecutableDocument来定义这个查询:

import 'package:brick_graphql/src/document/executable_document.dart';

final String getUserQuery = r'''
  query GetUser($id: ID!) {
    user(id: $id) {
      id
      name
      email
    }
  }
''';

final GQLExecutableDocument getUserExecutableDocument =
    GQLExecutableDocument.parse(parseString(getUserQuery));

注意:parseString函数需要从graphql_parser包中导入,但这个包通常是由brick_graphql依赖自动引入的。

4. 执行查询并处理响应

使用GraphQLClient实例执行查询,并处理响应数据。

import 'package:flutter/material.dart';
import 'package:brick_graphql/brick_graphql.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('Flutter GraphQL Demo')),
        body: GraphQLProvider(
          client: client,
          child: UserInfoScreen(),
        ),
      ),
    );
  }
}

class UserInfoScreen extends StatefulWidget {
  @override
  _UserInfoScreenState createState() => _UserInfoScreenState();
}

class _UserInfoScreenState extends State<UserInfoScreen> {
  User? user;

  @override
  void initState() {
    super.initState();
    _fetchUserData();
  }

  Future<void> _fetchUserData() async {
    final QueryResult result = await widget.client.value.query(
      getUserExecutableDocument,
      variables: {'id': '123'}, // 替换为实际的用户ID
    );

    if (result.hasExceptions) {
      print('Error fetching user data: ${result.exceptions!.first}');
    } else if (result.data != null) {
      final Map<String, dynamic> userData = result.data!['user'];
      setState(() {
        user = User.fromJson(userData);
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: user == null
          ? CircularProgressIndicator()
          : Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Text('Name: ${user!.name}'),
                Text('Email: ${user!.email}'),
              ],
            ),
    );
  }
}

class User {
  final String id;
  final String name;
  final String email;

  User({required this.id, required this.name, required this.email});

  factory User.fromJson(Map<String, dynamic> json) {
    return User(
      id: json['id'] as String,
      name: json['name'] as String,
      email: json['email'] as String,
    );
  }
}

总结

这个示例展示了如何在Flutter应用中使用brick_graphql插件来配置GraphQL客户端、定义和执行查询以及处理响应数据。请根据你的实际需求调整代码中的GraphQL端点、查询和变量。

回到顶部