Flutter数据标准化处理插件normalize的使用

发布于 1周前 作者 h691938207 来自 Flutter

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.keyFieldsFieldPolicy.keyArgs 只接受字符串的扁平列表,不支持函数或嵌套的字符串列表。此外,FieldPolicy.mergeFieldPolicy.read 也尚未实现。

如果您有任何问题或需要进一步的帮助,请随时联系我!


更多关于Flutter数据标准化处理插件normalize的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于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类,它实现了normalizedenormalize方法,用于将数据缩放到0到1的范围。然后,我们在NormalizeExample组件的initState方法中调用normalizeList函数(注意,normalizeList函数并不是normalize插件的一部分,这里我们假设它是这样使用的,实际中你可能需要手动调用normalize方法并处理结果)。

注意:normalize插件的实际API可能有所不同,具体使用时请参考官方文档和插件的实际API。如果normalize插件提供了内置的标准化方法,你可能不需要自定义MinMaxScaler类,而是直接使用插件提供的方法。

此外,这个示例代码主要是展示如何在Flutter应用中处理数据标准化,实际开发中你可能需要根据具体需求调整代码。

回到顶部