关于GraphQL和Flutter的使用步骤指南

359 阅读3分钟

GraphQL:准确地获得你所需要的东西,而不是其他东西

让我们来看看两种情况。

  • getUser API返回一堆不相关的数据,而你只需要一个电子邮件地址
  • 你必须检索4-5个API来建立一个屏幕

这就是 GraphQL 的用处,在这篇文章中,我将演示如何一步步创建 GraphQL 服务器和 Flutter 客户端。

作为一个应用程序的开发者,你可能会想,我为什么要关心服务器呢?难道我不能直接下载 repo 吗?事实上,根据GraphQL的性质,前端工程师很可能会维护和更新服务器端的代码,所以了解基础知识会有帮助。

Apollo GraphQL服务器

package.json

在项目根目录下创建一个package.json文件,这个文件包含项目的配置数据和依赖关系,它看起来像这样。

{
  "name": "graphql-server",
  "version": "1.0.0",
  "main": "app.js",
  "scripts": {...},
  "dependencies": {
    "apollo-datasource-http": "^0.10.0",...
  }
}

数据源

在GraphQL中获取数据有几种方式:从REST API中获取,从GraphQL api中获取,从数据库中获取,这些都是通过数据源完成的。这时,你可以减少大量的api调用,并将其合并为一个。假设我们需要一个api调用来获取用户,一个调用来获取项目列表,那么我们就需要创建两个独立的数据源文件。

const userdata = new (class UserAPI extends HTTPDataSource {
  constructor() {
       const pool = new Pool("http://localhost:8080/");
       super(baseURL, {pool})
  }
  async getUser(userID) {
       return this.get(`/company/${userID}`, {});
  }})
module.exports = userdata

第二个数据源文件来获取一个项目列表

//second data source file to fetch list of items
const listdata = new (class UserAPI extends HTTPDataSource {
  constructor() {
       const pool = new Pool("http://localhost:8080/");
       super(baseURL, {pool})
  }
  async getList(itemID) {
       return this.get(`/list`, {query: {itemID: itemID}
  });
}})
module.exports = listdata

最后,使用一个索引文件将这两个API合并成一个。

const datasources = () => {
   return {
       userAPI: UserAPI,
       listAPI: ListAPI,
   }
};
module.exports = datasources;

模式和解析器

现在我们有了合并API的功能,GraphQL的另一个重要特征是准确地查询你所需要的东西,这是用Schema和Resolver处理的。模式是定义数据,而解析器则负责填充数据。

//Schema
const { gql } = require('apollo-server');
const baseSchema = gql`
   type Query {_: Boolean}
   type Mutation {_: Boolean}
   type User {
      userID: String!
      userName: String!
   }`
module.exports = baseSchema;
//Resolver
const userResolvers = {
   Query: {user: (id) => {}}};
module.exports = userResolvers;

GraphQL服务器

首先,我们需要安装Apollo服务器。

npm install apollo-server graphql 

现在让我们创建一个GraphQL服务器文件 - project/src/app.js。

const { ApolloServer } = require('apollo-server');
const typeDefs = require('./schema');
const resolvers = require('./resolvers');
const datasources = require('./datasources');
const server = new ApolloServer({typeDefs,resolvers,dataSources});
server.listen({port: 8080}, () => {
   console.log('Server is running');
});

启程开始

npm install
npm start

目标架构

你要用GraphQL来代替REST吗?可能不是。最好是将GraphQL作为REST API服务前面的一个额外层。通过这种方式,后端团队可以专注于构建核心服务,而前端团队可以以最适合其性能的方式优化服务器响应。


Flutter GraphQL客户端

过渡期的移动应用层包含:表现形式、领域和数据,而通常数据层负责获取、映射和存储数据。有没有更好的方法呢?如果我们可以抛弃数据层呢?有了GraphQL,这是有可能的。

在Flutter中使用GraphQL是相当容易的,不幸的是,在写这篇文章的时候,还没有一个Apollo Flutter库,因此我们将只使用GraphQL库。让我们来看看依赖性。

name: graph_ql
...
dependencies:
    graphql_flutter: ^4.0.0-beta

在main()中启动并创建GraphQL服务器

void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
     ValueNotifier<GraphQLClient> client =    ValueNotifier(GraphQLClient(link:HttpLink('http://localhost:8080/graphql')));
     
     return GraphQLProvider(
          client: client,
          child: MaterialApp(home: UserScreen()));
     }
}

创建一个GraphQL方案

final String getItem = """
query {
   item(id: "1") {user(id: "2") {name}}
}""";

在一个Widget中使用数据

class ItemScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
       body: Container(
          child: Query(
             options: WatchQueryOptions(document: gql(getItem), fetchPolicy: FetchPolicy.networkOnly),
             builder: (QueryResult result, {VoidCallback refetch,    FetchMore fetchMore}) {
               if (result.data == null) return Text('Error')
               if (result.isLoading) return Text('Loading');
               return _buildUserWidget(result.data);
               })));
  }}

🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉