使用生成的 Flutter SDK

Firebase SQL Connect 客户端 SDK,您可以直接从 Firebase 应用调用服务器端查询和 变更。在设计要部署到 SQL Connect 服务的架构、查询和变更时,您可以并行生成自定义客户端 SDK。然后,您可以将此 SDK 中的方法集成到客户端逻辑中。

正如我们在其他地方提到的,请务必注意,SQL Connect 查询和变更不是由客户端代码提交并在 服务器上执行的。相反,部署后,SQL Connect 操作会像 Cloud Functions 一样存储在 服务器上。这意味着,您需要部署相应的客户端更改,以避免影响现有用户(例如,使用旧版应用的用户)。

因此,SQL Connect 为您提供了一个开发者环境和 工具,让您可以对服务器部署的架构、查询和变更进行原型设计。 它还会在您进行原型设计时自动生成客户端 SDK。

在您迭代更新服务和客户端应用后,服务器端和客户端更新都可以部署了。

什么是客户端开发工作流?

如果您已阅读使用入门,则应该已经 了解 SQL Connect 的整体开发流程。在本指南中,您将找到有关从架构生成 Flutter SDK 以及使用客户端查询和变更的更详细信息。

总而言之,如需在客户端应用中使用生成的 Flutter SDK,您需要执行以下前提步骤:

  1. 将 Firebase 添加到您的 Flutter 应用。
  2. 安装 flutterfire CLI dart pub global activate flutterfire_cli
  3. 运行 flutterfire configure

然后:

  1. 开发应用架构。
  2. 设置 SDK 生成:

  3. 初始化客户端代码并导入库

  4. 实现对查询变更的调用。

  5. 设置和使用 SQL Connect 模拟器 并 进行迭代。

生成 Flutter SDK

使用 Firebase CLI 在应用中设置 SQL Connect 生成的 SDK。 init 命令应检测当前文件夹中的所有应用并自动安装生成的 SDK。

firebase init dataconnect:sdk

在原型设计期间更新 SDK

如果您安装了 SQL Connect VS Code 扩展程序,它将始终使生成的 SDK 保持最新状态。

如果您不使用 SQL Connect VS Code 扩展程序,则可以使用 Firebase CLI 使生成的 SDK 保持最新状态。

firebase dataconnect:sdk:generate --watch

在 build 流水线中生成 SDK

您可以使用 Firebase CLI 在 CI/CD build 流程中生成 SQL Connect SDK。

firebase dataconnect:sdk:generate

设置客户端代码

初始化 SQL Connect 应用

首先,按照 标准的 Firebase 设置说明初始化应用。

然后,安装 SQL Connect 插件:

flutter pub add firebase_data_connect

初始化 SQL Connect Flutter SDK

使用您用于设置 SQL Connect 的信息初始化 SQL Connect 实例(所有信息都可在 Firebase 控制台的 SQL Connect 标签页中找到)。

导入库

初始化客户端代码需要两组导入:常规 SQL Connect导入和特定的生成的 SDK 导入。

// general imports
import 'package:firebase_data_connect/firebase_data_connect.dart';

// generated queries and mutations from SDK
import 'generated/movies.dart';

在客户端使用查询

生成的代码将附带预定义的查询引用。您只需导入并对其调用 execute 即可。

import 'generated/movies.dart';

await MoviesConnector.instance.listMovies().execute();

调用 SDK 查询方法

以下示例使用了这些操作快捷方式函数:

import 'generated/movies.dart';

function onBtnClick() {
  // This will call the generated Dart from the CLI and then make an HTTP request to the server.
  MoviesConnector.instance.listMovies().execute().then(data => showInUI(data)); // == MoviesConnector.instance.listMovies().ref().execute();
}

可选字段

某些查询可能包含可选字段。在这些情况下,Flutter SDK 会公开构建器方法,并且必须单独设置。

例如,调用 createMovie 时,字段 rating 是可选的,因此您需要在构建器函数中提供该字段。

await MoviesConnector.instance.createMovie({ title: 'Empire Strikes Back', releaseYear: 1980, genre: "Sci-Fi"}).rating(5).execute();

订阅更改

您可以订阅更改(每次执行查询时都会更新)。

QueryRef<ListMoviesData, void> listRef = MoviesConnector.instance.listMovies().ref();

// subscribe will immediately invoke the query if no execute was called on it previously.
listRef.subscribe().listen((data) {
  updateUIWithMovies(data.movies);
});

await MoviesConnector.instance.createMovie({ title: 'Empire Strikes Back', releaseYear: 1980, genre: "Sci-Fi" }).rating(5).execute();
await listRef.execute(); // will update the subscription above`

处理枚举字段的更改

应用的架构可以包含枚举, GraphQL 查询可以访问这些枚举

随着应用设计发生变化,您可能会添加新的枚举支持的值。例如,假设您在应用的生命周期后期决定向 AspectRatio 枚举添加 FULLSCREEN 值。

SQL Connect 工作流中,您可以使用本地开发工具来 更新查询和 SDK。

但是,在发布客户端的更新版本之前,较旧的已部署客户端可能会中断。

弹性实现示例

生成的 SDK 会强制处理未知值。也就是说,客户端代码必须将 EnumValue 对象解包为 KnownUnknown

final result = await MoviesConnector.instance.listMovies().execute();

if (result.data != null && result.data!.isNotEmpty) {
  handleEnumValue(result.data![0].aspectratio);
}

void handleEnumValue(EnumValue<AspectRatio> aspectValue) {
  if (aspectValue.value != null) {
    switch(aspectValue.value!) {
      case AspectRatio.ACADEMY:
        print("This movie is in Academy aspect");
        break;
      case AspectRatio.WIDESCREEN:
        print("This movie is in Widescreen aspect");
        break;
      case AspectRatio.ANAMORPHIC:
        print("This movie is in Anamorphic aspect");
        break;
      case AspectRatio.IMAX:
        print("This movie is in IMAX aspect");
    }
  } else {
    print("Unknown aspect ratio detected: ${aspectValue.stringValue}");
  }
}

启用客户端缓存

SQL Connect 具有可选的客户端缓存功能,您 可以通过修改 connector.yaml 文件来启用此功能。启用此功能后,生成的客户端 SDK 会在本地缓存查询响应,这可以减少应用发出的数据库请求数量,并使应用中依赖于数据库的部分在网络可用性中断时也能正常运行。

如需启用客户端缓存,请向连接器配置添加客户端缓存配置:

generate:
  javascriptSdk:
    outputDir: ../dart/
    package: "dataconnect_generated"
    clientCache:
      maxAge: 5s
      storage: memory

此配置有两个参数,均为可选参数:

  • maxAge:缓存的响应在客户端 SDK 提取新值之前可以保留的最长时间。示例:“0”“30 秒”“1 小时 30 分钟”。

    maxAge 的默认值为 0,这意味着响应会被缓存,但客户端 SDK 始终会提取新值。只有在为 execute() 指定 CACHE_ONLY 且从 subscribe() 返回初始结果时,才会使用缓存的值。

  • storage:客户端 SDK 可以配置为将响应缓存在 persistent 存储空间或 memory 存储空间中。缓存在 persistent 存储空间中的结果在应用重新启动后将保持不变。以 Android 或 iOS 为目标平台时,默认值为 persistent。以 Web 浏览器为目标平台时,仅支持 memory 存储空间。

更新连接器的缓存配置后,重新生成客户端 SDK 并重新构建应用。完成此操作后,execute()subscribe() 将缓存响应并根据您配置的政策使用缓存的值。这通常会自动发生,您无需执行任何额外操作;但是,请注意以下事项:

  • execute() 的默认行为如上所述:如果查询的结果已缓存,并且缓存的值未超过 maxAge,则使用缓存的值。此默认行为称为 PREFER_CACHE 政策。

    您还可以为 execute() 的各个调用指定仅提供缓存的值 (CACHE_ONLY) 或无条件地从服务器提取新值 (SERVER_ONLY)。

    await queryRef.execute(fetchPolicy: QueryFetchPolicy.cacheOnly);
    
    await queryRef.execute(fetchPolicy: QueryFetchPolicy.serverOnly);
    
  • 当您调用 subscribe() 时,无论 maxAge 设置如何,它都会始终立即返回缓存的内容(如果存在)。后续对 execute() 的调用将根据配置的 maxAge 通知监听器。

在客户端使用变更

变更的访问方式与查询相同。

await MoviesConnector.instance.createMovie({ title: 'Empire Strikes Back', releaseYear: 1980, genre: "Sci-Fi" }).rating(5).execute();

对 Flutter 应用进行原型设计和测试

为客户端插桩以使用本地模拟器

您可以使用 SQL Connect 模拟器,无论是通过 SQL Connect VS Code 扩展程序还是通过 CLI。

在这两种情况下,检测应用以连接到模拟器的方式是相同的。

import 'package:firebase_data_connect/firebase_data_connect.dart';
import 'generated/movies.dart';

MoviesConnector.instance.dataConnect
          .useDataConnectEmulator('127.0.0.1', 9399);

// Make calls from your app
QueryRef<ListMoviesData, void> ref = MoviesConnector.instance.listMovies.ref();

如需切换到生产资源,请注释掉用于连接到模拟器的行。

Dart SDK 中的数据类型

SQL Connect 服务器表示常见的 GraphQL 数据类型。这些类型在 SDK 中的表示方式如下。

SQL Connect 类型 Dart
时间戳 firebase_data_connect.Timestamp
整数(32 位) int
日期 DateTime
UUID string
Int64 int
浮点数 double
布尔值 bool
不限 firebase_data_connect.AnyValue