Flutter数据标准化处理插件normalize的使用
Flutter数据标准化处理插件normalize的使用
插件介绍
normalize
插件主要用于对 GraphQL 操作的数据进行标准化和去标准化处理。通过 normalize
函数,可以将 GraphQL 查询的结果写入一个标准化的 Map
中,从而有效地缓存查询结果。这个函数会遍历 GraphQL AST,并且只包含在 GraphQL 文档中指定的字段。
特点
- Fragments:支持片段
- Variables:支持变量
- Interface & Union types:支持接口和联合类型
- Aliases:支持别名
- TypePolicy(参见 Apollo):支持自定义类型策略
依赖项
此库依赖于 gql 库。
使用方法
假设我们有以下查询:
import 'package:gql/language.dart';
import 'package:gql/ast.dart';
import 'package:normalize/normalize.dart';
final DocumentNode query = parseString("""
query TestQuery {
posts {
id
__typename
author {
id
__typename
name
}
title
comments {
id
__typename
commenter {
id
__typename
name
}
}
}
}
""")
执行该查询后得到如下响应数据:
final Map<String, dynamic> data = {
"posts": [
{
"id": "123",
"__typename": "Post",
"author": {
"id": "1",
"__typename": "Author",
"name": "Paul",
},
"title": "My awesome blog post",
"comments": [
{
"id": "324",
"__typename": "Comment",
"commenter": {
"id": "2",
"__typename": "Author",
"name": "Nicole",
}
}
],
}
]
};
我们可以运行 normalize
函数来标准化这些数据:
final normalizedMap = {};
normalizeOperation(
merge: (dataId, value) =>
(normalizedMap[dataId] ??= {}).addAll(value),
document: query,
data: data,
);
print(normalizedMap);
这将产生如下标准化结果:
{
"Query": {
"posts": [
{"$ref": "Post:123"}
]
},
"Post:123": {
"id": "123",
"__typename": "Post",
"author": {"$ref": "Author:1"},
"title": "My awesome blog post",
"comments": [
{"$ref": "Comment:324"}
],
},
"Author:1": {
"id": "1",
"__typename": "Author",
"name": "Paul",
},
"Comment:324": {
"id": "324",
"__typename": "Comment",
"commenter": {"$ref": "Author:2"}
},
"Author:2": {
"id": "2",
"__typename": "Author",
"name": "Nicole",
}
}
如果稍后需要去标准化这些数据(例如从缓存中读取),可以通过调用 denormalize
来实现:
denormalizeOperation(
document: query,
read: (dataId) => normalizedMap[dataId],
)
完整示例 Demo
下面是一个完整的示例,展示了如何在一个 Flutter 应用中使用 normalize
插件。
import 'package:flutter/material.dart';
import 'package:gql/language.dart';
import 'package:gql/ast.dart';
import 'package:normalize/normalize.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('Normalize Plugin Demo')),
body: Center(child: MyHomePage()),
),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final DocumentNode query = parseString("""
query TestQuery {
posts {
id
__typename
author {
id
__typename
name
}
title
comments {
id
__typename
commenter {
id
__typename
name
}
}
}
}
""");
final Map<String, dynamic> data = {
"posts": [
{
"id": "123",
"__typename": "Post",
"author": {
"id": "1",
"__typename": "Author",
"name": "Paul",
},
"title": "My awesome blog post",
"comments": [
{
"id": "324",
"__typename": "Comment",
"commenter": {
"id": "2",
"__typename": "Author",
"name": "Nicole",
}
}
],
}
]
};
late Map<String, dynamic> normalizedMap;
@override
void initState() {
super.initState();
// Normalize the data
normalizedMap = {};
normalizeOperation(
merge: (dataId, value) =>
(normalizedMap[dataId] ??= {}).addAll(value),
document: query,
data: data,
);
}
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text("Normalized Data:"),
Expanded(
child: SingleChildScrollView(
child: Text(normalizedMap.toString()),
),
),
SizedBox(height: 20),
ElevatedButton(
onPressed: () {
// Denormalize the data
final denormalizedData = denormalizeOperation(
document: query,
read: (dataId) => normalizedMap[dataId],
);
showDialog(
context: context,
builder: (context) => AlertDialog(
title: Text("Denormalized Data"),
content: SingleChildScrollView(
child: Text(denormalizedData.toString()),
),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: Text("Close"),
)
],
),
);
},
child: Text("Denormalize Data"),
),
],
),
);
}
}
在这个示例中,我们创建了一个简单的 Flutter 应用程序,它演示了如何使用 normalize
插件来标准化和去标准化 GraphQL 查询的结果。当用户点击按钮时,应用程序会显示去标准化后的原始数据。
局限性
目前,TypePolicy.keyFields
和 FieldPolicy.keyArgs
只接受字符串的扁平列表,不支持函数或嵌套的字符串列表。此外,FieldPolicy.merge
和 FieldPolicy.read
也尚未实现。
如果您有任何问题或需要进一步的帮助,请随时联系我!
更多关于Flutter数据标准化处理插件normalize的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter数据标准化处理插件normalize的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是如何在Flutter中使用normalize
插件进行数据标准化处理的示例代码。normalize
插件通常用于将不同范围的数据缩放到一个统一的范围内(如0到1),这对于机器学习、数据分析以及某些UI处理非常有用。
首先,确保你已经在pubspec.yaml
文件中添加了normalize
插件的依赖:
dependencies:
flutter:
sdk: flutter
normalize: ^x.y.z # 替换为最新版本号
然后,运行flutter pub get
来安装依赖。
接下来,你可以在你的Dart代码中导入并使用normalize
插件。以下是一个示例,展示了如何将一个包含不同范围数据的列表标准化到0到1的范围内:
import 'package:flutter/material.dart';
import 'package:normalize/normalize.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Normalize Example'),
),
body: NormalizeExample(),
),
);
}
}
class NormalizeExample extends StatefulWidget {
@override
_NormalizeExampleState createState() => _NormalizeExampleState();
}
class _NormalizeExampleState extends State<NormalizeExample> {
List<double> rawData = [10, 200, 50, 800, 12];
List<double>? normalizedData;
@override
void initState() {
super.initState();
normalizedData = normalizeList(rawData, MinMaxScaler());
}
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Raw Data:', style: TextStyle(fontSize: 18)),
...rawData.asMap().entries.map((entry) {
return Text('Index ${entry.key}: ${entry.value}');
}),
SizedBox(height: 16),
Text('Normalized Data:', style: TextStyle(fontSize: 18)),
...(normalizedData ?? []).asMap().entries.map((entry) {
return Text('Index ${entry.key}: ${entry.value.toStringAsFixed(2)}');
}),
],
),
);
}
}
// 示例:MinMaxScaler,将数据缩放到0到1的范围
class MinMaxScaler implements Normalizer<List<double>, List<double>> {
@override
List<double> normalize(List<double> data) {
double min = data.reduce((a, b) => a < b ? a : b);
double max = data.reduce((a, b) => a > b ? a : b);
return data.map((value) => (value - min) / (max - min)).toList();
}
@override
List<double> denormalize(List<double> data, List<double> originalData) {
double min = originalData.reduce((a, b) => a < b ? a : b);
double max = originalData.reduce((a, b) => a > b ? a : b);
return data.map((value) => value * (max - min) + min).toList();
}
}
在这个示例中,我们定义了一个自定义的MinMaxScaler
类,它实现了normalize
和denormalize
方法,用于将数据缩放到0到1的范围。然后,我们在NormalizeExample
组件的initState
方法中调用normalizeList
函数(注意,normalizeList
函数并不是normalize
插件的一部分,这里我们假设它是这样使用的,实际中你可能需要手动调用normalize
方法并处理结果)。
注意:normalize
插件的实际API可能有所不同,具体使用时请参考官方文档和插件的实际API。如果normalize
插件提供了内置的标准化方法,你可能不需要自定义MinMaxScaler
类,而是直接使用插件提供的方法。
此外,这个示例代码主要是展示如何在Flutter应用中处理数据标准化,实际开发中你可能需要根据具体需求调整代码。