Flutter
GraphQL
Flutter与GraphQL集成示例:构建完整应用程序教程
25 分
下载一个 flutter graphql 项目及其源代码并开始使用 back4app 介绍 在本教程中,我们将构建一个应用程序,该应用程序将通过 graphql 从 back4app 后端解析数据。正如您所知,graphql 是一种开源数据查询和操作语言,用于 api,并且是一个用于使用现有数据满足查询的运行时。back4app 是一个低代码的后端即服务(基于开源 parse 平台),它帮助开发人员快速构建可扩展和可扩展的移动和 web 应用程序。 目标 主要目标是构建一个简单的应用程序,该应用程序将显示编程语言及其保存类型格式的列表。 在本文的结尾,我们希望您能够: 使用 graphql 在 back4app 上进行 api 调用; 从 graphql api 获取数据; 在您的 flutter 应用中获取数据。 先决条件 要完成本教程,您需要: 一个用于编写 flutter 代码的 ide,如 android studio 或 flutter。不过我们将在本教程中使用 android studio。 一个可以在这里创建的 back4app 账户: https //www back4app com/ https //pub dev/packages/graphql flutter 1 从 github 克隆项目到 android studio 访问 https //github com/templates back4app/flutter graphql , 下载 zip 文件,解压缩并在您的 flutter ide 中打开它。 要完成此步骤,请将压缩文件中的文件夹拖到桌面,打开 android studio,然后点击打开现有的 android studio 项目。项目目录通常是‘ c \users\username\desktop\back4app graphql starting code ’。 但这对于不同的用户可能会有所不同。 打开项目并转到 lib\main dart lib\main dart 文件。你会看到很多错误,不用担心,只需按下所有‘ 获取依赖项 ’所有错误就会消失。如果没有,那么只需按下‘ 升级依赖项 ’。 你在 main dart main dart 中的代码应该是这样的。 1 import 'package\ flutter/material dart'; 2 import 'package\ graphql flutter/graphql flutter dart'; 3 import 'consonents dart'; 4 5 void main() { 6 runapp(myapp()); 7 } 8 9 class myapp extends statelesswidget { 10 @override 11 widget build(buildcontext context) { 12 return materialapp( 13 home myhomepage(), 14 ), 15 ); 16 } 17 } 18 class myhomepage extends statefulwidget { 19 @override 20 myhomepagestate createstate() => myhomepagestate(); 21 } 22 23 class myhomepagestate extends state\<myhomepage> { 24 25 @override 26 widget build(buildcontext context) { 27 return safearea( 28 child scaffold( 29 appbar appbar( 30 title text('parsing data using graphql', 31 ), 32 ), 33 body container(), 34 ),); 35 } 36 } 如果你现在打开应用程序,你只会在你的模拟器/设备上看到一个空白屏幕,只有一个标题为 ‘使用 graphql 解析数据’ 我们将处理 main dart main dart 文件,我们的重要值存储在 consonents dart consonents dart 中,我们可以直接从那里使用它。我们将需要 graphql flutter graphql flutter 依赖项来在我们的应用中使用 graphql 这个 graphql flutter graphql flutter 是最受欢迎的 flutter graphql 客户端。它帮助我们直接在代码中使用 graphql 查询。它为我们提供了 graphqlclient graphqlclient , graphqlprovider graphqlprovider 和许多其他有用的组件,帮助我们直接从数据库解析数据,甚至不需要使用 streambuilder streambuilder 该包为我们提供了许多功能,包括 订阅 内存缓存 离线缓存同步 乐观结果 graphql 文件上传 你可以通过在 pubspec yaml pubspec yaml 文件中写入以下代码来导入它 dependencies graphql flutter ^ 3 1 0 查看更多关于 graphql flutter graphql flutter 的信息,访问 https //pub dev/packages/graphql flutter 所有依赖项已经预先安装,您可以继续进行下一步。 2 在 back4app 中创建后端 在 https //www back4app com/ 网站注册后,您可以继续下一步并创建一个新应用。点击 ‘构建新应用’ 。给它起一个与您的项目名称相同的名称,这里是 ‘back4app graphql’ 现在向下滚动到 服务器设置 在左侧,选择 设置 管理 parse 服务器卡片,然后从列表中选择 ‘3 10 0 parse server 3 10 0’ 。现在按下下面的保存按钮,等待保存完成。 现在返回到 核心 (在左侧),选择 api 控制台 , 然后从中选择 graphql 控制台 。 这是您可以编写和测试您的 graphql 查询/变更代码的窗口。让我们继续下一步。 3 通过 graphql 创建和获取数据 现在,让我们使用 graphql api 控制台在 back4app 上测试 graphql api。首先,将以下查询粘贴到左侧代码框中: 1 mutation createclass { 2 createclass(input { 3 name "language" 4 schemafields { 5 addstrings \[{name "name"}{name "saveformat"}] 6 } 7 }){ 8 class{ 9 schemafields{ 10 name 11 typename 12 } 13 } 14 } 15 } 16 上面的代码将创建一个名为“language”的类。让我们用一些行填充这个新类: 1 mutation createobject{ 2 createlanguage(input {fields {name "python", saveformat " py"}}){ 3 language{ 4 name, 5 saveformat 6 } 7 } 8 } 如果您的操作成功,您将在 graphql playground 的右侧代码框中看到此消息: 1 { 2 "data" { 3 "createlanguage" { 4 "language" { 5 "name" "python", 6 "saveformat" " py" 7 } 8 } 9 } 10 } 变更用于创建或更改一个类。通过运行上述变更,我们将创建一个名为 language 的新类,包含数据字段: name “python” saveformat “ py” 重复该过程,并在同一类中为以下内容创建两个对象: name “c” 和 saveformat “ c” name “java” 和 saveformat “ java”。 这将是该变更的内容: 1 mutation createobject{ 2 createlanguage(input {fields {name "c", saveformat " c"}}){ 3 language{ 4 name, 5 saveformat 6 } 7 } 8 } java 1 mutation createobject{ 2 createlanguage(input {fields {name "java", saveformat " java"}}){ 3 language{ 4 name, 5 saveformat 6 } 7 } 8 } 现在让我们看看我们类中的所有数据 languages 为了读取数据,我们使用 query 所以请继续输入下面的命令。 1 query findlanguages{ 2 languages{ 3 count, 4 edges{ 5 node{ 6 name, 7 saveformat 8 } 9 } 10 } 11 } 在 query findlanguage query findlanguage 中,‘findlanguage’只是你查询命令的名称,你甚至可以将其命名为其他任何名称。我们使用 find(classname "") find(classname "") 命令来查找特定类的所有元素。 count count , 返回类中元素的数量,所有元素都显示在 result result 对象中。 上述查询将返回以下内容: 1 { 2 "data" { 3 "languages" { 4 "count" 3, 5 "edges" \[ 6 { 7 "node" { 8 "name" "python", 9 "saveformat" " py" 10 } 11 }, 12 { 13 "node" { 14 "name" "c", 15 "saveformat" " c" 16 } 17 }, 18 { 19 "node" { 20 "name" "java", 21 "saveformat" " java" 22 } 23 } 24 ] 25 } 26 } 27 } 您可以在以下链接中查看所有其他查询: https //blog back4app com/graphql on parse/ 现在,让我们继续下一步。 4 在我们的应用中设置 graphql 让我们开始编写我们的应用。在此之前,您必须在您的 lib\consonents dart lib\consonents dart 文件中做一些事情: 复制 graphql 窗口顶部历史按钮旁边的 graphql 链接,并将其粘贴为 kurl 字符串数据类型。 现在移动到页面底部,复制 http headers 中的代码,只复制冒号( )右侧的代码,并将其与各自的名称粘贴到 lib\consonents dart lib\consonents dart 文件中: 文件应包含以下代码: 1 string kparseapplicationid= "application id copied from headers"; 2 string kparseclientkey = "client key copied from header"; 3 string kurl= "url copied"; 4 // replace "application id copied from headers", "client key copied from header", "url copied" with real keys/ids copied 5 //from http headers tab 现在转到 main dart main dart 文件,前往 myapp 无状态小部件,并在 return return materialapp() materialapp() 1 final httplink httplink = httplink( 2 uri kurl, 3 headers { 4 'x parse application id' kparseapplicationid, 5 'x parse client key' kparseclientkey, 6 }, 7 ); httplink 来自 flutter graphql dart ,并接受带有两个参数的 httplink() 小部件。第一个是 back4app 上的 graphql api url。第二个是用于在 back4app api 上进行身份验证所需的头信息。在此部分之后,您需要包含 graphql 客户端代码(解释是什么),复制下面的代码,然后粘贴到 httplink 部分下: 1 valuenotifier\<graphqlclient> client = valuenotifier( 2 graphqlclient( 3 cache optimisticcache(dataidfromobject typenamedataidfromobject), 4 link httplink, 5 ), 6 ); 现在我们已经将链接和缓存方法提供给我们的 graphqlclient。我们通过 valuenotifier 完成了这一点,并将其命名为 client。让我们用 graphqlprovider 包裹 myhomepage() 小部件,该小部件是 materialapp 的子项,并将 myhomepage() 作为其客户端传递。在 graphqlprovider 中添加另一个参数,即 client,并将 client(我们 valuenotifier 的名称)传递给它。这就是你的 myapp 类现在应该的样子: 1 class myapp extends statelesswidget { 2 @override 3 widget build(buildcontext context) { 4 final httplink httplink = httplink( 5 uri kurl, 6 headers { 7 'x parse application id' kparseapplicationid, 8 'x parse client key' kparseclientkey, 9 //'x parse rest api key' kparserestapikey, 10 },//getheaders() 11 ); 12 valuenotifier\<graphqlclient> client = valuenotifier( 13 graphqlclient( 14 cache optimisticcache(dataidfromobject typenamedataidfromobject), 15 link httplink, 16 ), 17 ); 18 return materialapp( 19 home graphqlprovider( 20 child myhomepage(), 21 client client, 22 ), 23 ); 24 } 25 } 让我们调用 api 并获取数据 5 进行 api 调用 现在我们将处理 myhomepagestate。我们将开始初始化一个名为 ‘query’ 的字符串数据类型,并将查询语句分配/传递给它,以查找我们 language 类中的所有数据。由于查询是多行的,我们将以三重引号传递查询。它看起来是这样的: 1 string query=''' 2 query findlanguages{ 3 languages{ 4 count, 5 edges{ 6 node{ 7 name, 8 saveformat 9 } 10 } 11 } 12 } 13 '''; 现在去 query() 小部件,在 scaffold 的 body 参数中,它有两个属性: 选项 构建器 然后将两个参数都传递为 null。这是你的构建方法的样子 1 widget build(buildcontext context) { 2 return safearea( 3 child scaffold( 4 appbar appbar( 5 title text('parsing data using graphql', 6 ), 7 ), 8 body query( 9 options null, 10 builder null 11 ), 12 ),); 13 } “ query() query() 小部件帮助我们编写 graphql 查询,并将帮助我们读取和获取数据。我们将把查询语句作为字符串传递给选项,并使用构建器参数构建小部件。 因此,将 queryoptions() 小部件作为选项传递,如下所示 1 options queryoptions( 2 documentnode gql(query), 3 ), 4 查询通过 queryoptions 中的 documentnode 参数传递。现在让我们在 builder 参数的帮助下构建。builder 方法接受一个具有三个参数的函数,即, queryresult 结果; refetch 重新获取; fetchmore 获取更多 现在,我们只需要关注 queryresult,它给我们提供查询的结果,我们可以通过 result data result data 所以让我们在下面编写代码 1 builder (queryresult result, { refetch refetch,fetchmore fetchmore,}) 2 { 3 if(result data==null){ 4 return center(child text("loading ",style textstyle(fontsize 20 0),)); 5 }else{ 6 return text('success'); 7 } 8 }, 在上面的代码中,我们正在访问数据。如果没有数据,我们返回一个文本小部件,内容为 ‘加载中…’ 否则我们将返回一个 text() 小部件,内容为 ‘成功’ 这是你的 myhomepage myhomepage 类在 main dart main dart 中应该是这样的 1 class myhomepage extends statefulwidget { 2 @override 3 myhomepagestate createstate() => myhomepagestate(); 4 } 5 6 class myhomepagestate extends state\<myhomepage> { 7 string name; 8 string saveformat; 9 string objectid; 10 11 string query = ''' 12 query findlanguages{ 13 languages{ 14 count, 15 edges{ 16 node{ 17 name, 18 saveformat 19 } 20 } 21 } 22 } 23 '''; 24 25 @override 26 widget build(buildcontext context) { 27 return safearea( 28 child scaffold( 29 appbar appbar( 30 title text( 31 'parsing data using graphql', 32 ), 33 ), 34 body query( 35 options queryoptions( 36 documentnode gql(query), 37 ), 38 builder ( 39 queryresult result, { 40 refetch refetch, 41 fetchmore fetchmore, 42 }) { 43 if (result data == null) { 44 return center( 45 child text( 46 "loading ", 47 style textstyle(fontsize 20 0), 48 ), 49 ); 50 } else{ 51 return text('success'); 52 } 53 } 54 ), 55 ), 56 ); 57 } 58 } 现在,启动应用程序并在重启后等待几秒钟。如果您在屏幕上看到 ‘success’ ,那么 恭喜!您已建立连接并调用了api。 6 从api获取和显示数据 我们将返回 listview\ builder() 小部件而不是返回文本小部件。请将以下代码写入返回 text('success') text('success') 1 return listview\ builder( 2 itembuilder (buildcontext context, int index){ 3 return listtile( 4 title text(result data\["languages"]\["edges"]\[index]\["node"]\['name']), 5 trailing text(result data\["languages"]\["edges"]\[index]\["node"]\['saveformat']), 6 ); 7 }, 8 itemcount result data\["languages"]\["edges"] length, 9 ); 现在,如果您回到back4app的api控制台中的graphql结果屏幕,我们输入了查找方法,结果如下 1 { 2 "data" { 3 "languages" { 4 "count" 3, 5 "edges" \[ 6 { 7 "node" { 8 "name" "python", 9 "saveformat" " py" 10 } 11 }, 12 { 13 "node" { 14 "name" "c", 15 "saveformat" " c" 16 } 17 }, 18 { 19 "node" { 20 "name" "java", 21 "saveformat" " java" 22 } 23 } 24 ] 25 } 26 } 27 } 因此,从上面的代码中,“python”的位置是 “数据” > “ 语言” > “计数” > “边缘” > “节点” > “名称” 还要注意名称在边缘的方括号‘\[]’内,这象征着它是边缘列表/数组的第一个元素。 所以我们需要进入这个位置来获取“python”,其他的也是如此。当我们写 result data result data , 我们进入 “数据” 位置。因此,为了给出其他位置,我们添加 \["location name"] \["location name"] 。所以“python”的位置将是 result data\["languages"]\["edges"]\[0]\["node"]\["name"] result data\["languages"]\["edges"]\[0]\["node"]\["name"] 使用 listview listview , 它需要两个参数, itemcount itemcount , 它告诉api调用中的元素数量, itembuilder itembuilder , 它接受一个带有参数的函数 (buildcontext context, int index) (buildcontext context, int index) 并返回一个列表小部件,我们将在其中显示数据。在这里,我们将使用 listtile 列表来显示数据 1 return listview\ builder( 2 itemcount result data\["languages"]\["edges"] length, 3 itembuilder (buildcontext context, int index){ 4 return listtile( 5 title text(result data\["languages"]\["edges"]\[index]\["node"]\['name']), 6 trailing text(result data\["languages"]\["edges"]\[index]\["node"]\['saveformat']), 7 ); 8 }, 9 10 ); 当我们用 text('success') text('success') 替换上面的 listview\ builder() 小部件时,我们首先传递 itemcount,其中我们传递结果列表中的元素数量,因此我们不需要再担心这个问题。在 itembuilder 中,我们返回一个 listtiles 列表,其中将包含 "name" "name" 的 "languages" "languages" 类,并在 "saveformat" "saveformat" 中作为尾部。注意我们使用了索引而不是结果后的任何数字,这就是 itemcount 处理的内容。 这就是你的 main dart main dart 现在应该看起来的样子 1 import 'package\ flutter/material dart'; 2 import 'package\ graphql flutter/graphql flutter dart'; 3 import 'consonents dart'; 4 import 'dart\ ui'; 5 6 void main() { 7 runapp(myapp()); 8 } 9 10 class myapp extends statelesswidget { 11 @override 12 widget build(buildcontext context) { 13 final httplink httplink = httplink( 14 uri 'https //parseapi back4app com/graphql', 15 headers { 16 'x parse application id' kparseapplicationid, 17 'x parse client key' kparseclientkey, 18 }, //getheaders() 19 ); 20 21 valuenotifier\<graphqlclient> client = valuenotifier( 22 graphqlclient( 23 cache optimisticcache(dataidfromobject typenamedataidfromobject), 24 link httplink, 25 ), 26 ); 27 28 return materialapp( 29 home graphqlprovider( 30 child myhomepage(), 31 client client, 32 ), 33 ); 34 } 35 } 36 37 class myhomepage extends statefulwidget { 38 @override 39 myhomepagestate createstate() => myhomepagestate(); 40 } 41 42 class myhomepagestate extends state\<myhomepage> { 43 string name; 44 string saveformat; 45 string objectid; 46 47 string query = ''' 48 query findlanguages{ 49 languages{ 50 count, 51 edges{ 52 node{ 53 name, 54 saveformat 55 } 56 } 57 } 58 } 59 '''; 60 61 @override 62 widget build(buildcontext context) { 63 return safearea( 64 child scaffold( 65 appbar appbar( 66 title text( 67 'parsing data using graphql', 68 ), 69 ), 70 body query( 71 options queryoptions( 72 documentnode gql(query), 73 ), 74 builder ( 75 queryresult result, { 76 refetch refetch, 77 fetchmore fetchmore, 78 }) { 79 if (result data == null) { 80 return center( 81 child text( 82 "loading ", 83 style textstyle(fontsize 20 0), 84 )); 85 } else { 86 return listview\ builder( 87 itembuilder (buildcontext context, int index) { 88 return listtile( 89 title text(result data\["languages"]\["edges"]\[index]\["node"] 90 \['name']), 91 trailing text(result data\["languages"]\["edges"]\[index] 92 \["node"]\['saveformat']), 93 ); 94 }, 95 itemcount result data\["languages"]\["edges"] length, 96 ); 97 } 98 }, 99 ), 100 ), 101 ); 102 } 103 } 这是我们的最终应用屏幕: 结论 现在你有一个连接到graphql api的flutter应用,可以在back4app上存储和检索数据。 我们不需要单独编码或解码json数据,这使我们的工作更简单、更快速,只需几行代码。 祝你有美好的一天!