什么是GraphQL
这篇文章主要是看一下如何在Flutter项目中使用GraphQL,如果不清楚GraphQL是什么,建议先看下官网对其介绍:
https://graphql.org/
https://www.howtographql.com
GraphQL体验
先介绍一个免费操作GraphQL语法的网站:
https://countries.trevorblades.com/
打开此链接,默认显示如下页面:
从图中也能看出,网站分3部分
左边方格中可以输入GraphQL的query语句
当点击屏幕中间的运行按钮后,右边方格中会显示查询的结果
网站最右方是一个DOCS按钮,可以点击查看具体的参数文档
先点击DOCS,看下具体可以查询那些参数如下
可以看出,在这个GraphQL Server中,我们可以查询 continents
、continent
、Countries
、Country
等多个不同的model。
我用查询Countries为例, 使用的查询语句为:
query Countries {
// 查询Countries model
countries {
// 并要求server返回带code、name、currency、emoji这4个参数的结果
code
name
currency
emoji
}
具体查询结果显示如下:
解释一下:因为我只在 query
语句中传入了 code、name、currency、emoji这四个参数,所以Server端只返回给我这4个参数的结果result。你可以试着传入一些其它参数,看一下返回结果是否会有变化。
Flutter中使用GraphQL
最后我们看下这篇文章的主题,如如何在Flutter中使用GraphQL。要在Flutter项目中使用GraphQL,我们需要使用一个库:graphql_flutter
具体实现步骤如下:
1 先在pubspec.yaml中添加依赖
2 构建HttpLink以及ValueNotifier
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
// HttpLink表示是往哪一个GraphQL Server发送query语句
final HttpLink httpLink =
HttpLink(uri: 'https://countries.trevorblades.com/');
// 创建ValueNotifier,并传入HttpLink。在ValueNotifier中还可以自定义网络请求缓存策略
final ValueNotifier<GraphQLClient> client = ValueNotifier<GraphQLClient>(
GraphQLClient(
link: httpLink as Link,
cache: OptimisticCache(
dataIdFromObject: typenameDataIdFromObject,
),
),
);
。。。
}
}
3 创建GraphQLProvider
创建好 ValueNotifier
之后,我们就可以创建 GraphQLProvider
这一个widget了。需要在 GraphQLProvider
中传入刚才创建的notifier,以及需要展示的child widget。
完整代码如下:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
/// HttpLink - A system of modular components for GraphQL networking.
final HttpLink httpLink =
HttpLink(uri: 'https://countries.trevorblades.com/');
final ValueNotifier<GraphQLClient> client = ValueNotifier<GraphQLClient>(
GraphQLClient(
link: httpLink as Link,
cache: OptimisticCache(
dataIdFromObject: typenameDataIdFromObject,
),
),
);
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: GraphQLProvider(
child: CountryListView(),
client: client,
),
);
}
}
可以看出,我们最后展示的是CountryListView
这一个widget。而在CountryListView
这个widget中,我们会调用graphql_flutter
提供的 Query
widget来发送GraphQL请求,并根据返回结果构建一个ListView组件,具体代码如下:
country_list.dart
import 'package:flutter/material.dart';
import 'package:graphql_flutter/graphql_flutter.dart';
class CountryListView extends StatelessWidget {
final String query = '''
query Countries {
countries {
code
name
currency
emoji
}
}
''';
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('List of Countries'),
),
body: Query(
options: QueryOptions(document: query),
builder: (QueryResult result, {VoidCallback refetch, FetchMore fetchMore }) {
if (result.loading) {
return Center(child: CircularProgressIndicator());
}
if (result.data == null) {
return Center(child: Text('Countries not found.'));
}
return _countriesView(result);
},
),
);
}
ListView _countriesView(QueryResult result) {
final countryList = result.data['countries'];
return ListView.separated(
itemCount: countryList.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(countryList[index]['name']),
subtitle: Text('Currency: ${countryList[index]['currency']}'),
leading: Text(countryList[index]['emoji']),
onTap: () {
final snackBar = SnackBar(
content:
Text('Selected Country: ${countryList[index]['name']}'));
Scaffold.of(context).showSnackBar(snackBar);
},
);
},
separatorBuilder: (context, index) {
return Divider();
},
);
}
}
其中,上面例子中的 query 字符串,就是我们在网站演示所使用的查询语句。最后运行效果如下:
总结
这篇文章介绍了如何在Flutter项目中简单快速的使用GraphQL。并实现了一个简单的Demo。但是上面显示Countries List的Demo有一个比较明显的问题,就是UI和数据严重绑定在一起,导致代码耦合性很高。
在实际的公司项目中,我们一般会将数据和UI进行分离,而常用的做法就是将GraphQL的 ValueNotifier<GraphQLClient> client 封装到Bloc中,然后在Widget中直接跟Bloc进行交互操作。网络上已经有大量介绍Bloc的文章,这里就不再赘述了。
最后安利一个Flutter交流群
为了屏蔽各种广告,目前微信群只开放了邀请加入的方式: