Flutter客户端插件dizzbase_client的使用

Flutter客户端插件dizzbase_client的使用

dizzbase 是一个为 Node.js Express 服务器设计的实时 PostgreSQL 后端即服务。客户端(如 Flutter/Dart 或 JavaScript/React)可以发送查询,并且这些查询会自动实时更新。

dizzbase 可以作为自托管 Supabase 的替代方案,如果需要一个轻量级且易于安装的解决方案。此外,如果您需要关系型数据库而不是文档数据库,也可以用它代替 Firebase。

此包是 dizzbase 的 Dart/Flutter 客户端。要了解如何安装和运行 Node.js 后端及其与 PostgreSQL 的集成,请参阅 npm 包

功能

该客户端通过 Dart Stream 提供对数据库查询的实时反馈。利用 Flutter StreamBuilder,当数据库中的数据发生变化时,小部件内容会自动更新。此外,Flutter/Dart 客户端还提供了用于更新/插入/删除 PostgreSQL 数据的接口,以及直接发送 SQL 语句的功能。

开始使用

客户端适用于 dizzbase 后端服务。首先在您的后端服务器上安装并配置 dizzbasenpm 包

安装客户端:

flutter pub add dizzbase_client

将包导入到您的 Flutter 应用程序中:

import 'package:dizzbase_client/dizzbase_client.dart';

在 Flutter 应用的主函数 main() 中,调用 DizzbaseConnection.configureConnection(...) 来配置您的后端服务的 URL 和访问令牌。

查看 pub.dev 上的“示例”页面,了解如何使用 API。

要了解 Dart/Flutter dizzbase 客户端的工作原理,请查看 flutter 演示客户端:

GitHub

演示客户端的 README.md 文件提供了有关如何使用 dizzbase_client API 的指导。

注意 StatefulWidgetinitState()dispose() 方法覆盖,了解如何创建和清理 dizzbase 连接,从而避免长生命周期客户端导致的后端内存泄漏。

使用方法

请参考以下示例详细说明如何使用客户端。

初始化

main() 中初始化 dizzbase 客户端。为了测试,您可以调用登录功能使用管理员演示用户(设置 main() 为异步以等待登录)。否则,您需要显示一个登录屏幕。请注意,只有在后端启用 JWT 时才需要登录并提供访问令牌。请参阅 dizzbase npm 后端包的 README.md 文件,了解如何启用/禁用 JWT 以及如何创建 API 访问令牌。

void main() async {
    DizzbaseConnection.configureConnection("http://localhost:3000", "...api access token...");
    await DizzbaseAuthentication.login(userName: "admin", password: "admin");
    runApp(const MyApp());
}    

使用 StreamBuilder 获取带有实时更新的数据

对于每个需要流式更新的小部件,创建/销毁 DizzbaseConnection 并创建如下所示的 Stream:

class MyWidget extends StatefulWidget {
  @override
  _MyWidgetState createState() => _MyWidgetState();
}

class _MyWidgetState extends State<MyWidget> {
  late DizzbaseConnection myDizzbaseConnection;
  Stream<DizzbaseResultRows>? _stream_1;
  Stream<DizzbaseResultRows>? _stream_2;
  Stream<DizzbaseResultRows>? _stream_3;
  Stream<DizzbaseResultRows>? _stream_4;

  @override
  void initState() {
    super.initState();

    // 创建一个新的连接到后端
    myDizzbaseConnection = DizzbaseConnection();

    // 通过主键检索单行
    _stream_1 = myDizzbaseConnection.streamFromQuery(DizzbaseQuery(table: MainTable("employee", pkey: 3)));

    // 演示如何在添加新订单时自动更新订单列表
    _stream_2 = myDizzbaseConnection.streamFromQuery(DizzbaseQuery(
      table: MainTable("order"),
      joinedTables: [JoinedTable('employee', joinToTableOrAlias: 'order', foreignKey: 'sales_rep_id')],
      filters: [Filter('employee', 'employee_id', 2)]
    ));

    // 使用 LIKE 语句进行搜索
    _stream_3 = myDizzbaseConnection.streamFromQuery(DizzbaseQuery(table: MainTable("employee"), 
      filters: [Filter('employee', 'employee_email', '%hotmail%', comparison: 'LIKE')]
    ));

    // 复杂查询
    _stream_4 = myDizzbaseConnection.streamFromQuery(DizzbaseQuery(
      table: MainTable('order'),
      joinedTables: [
        JoinedTable('customer'),
        JoinedTable('employee', joinToTableOrAlias: 'order', foreignKey: 'sales_rep_id', columns: ['employee_name', 'employee_email'], alias: 'seller'),
        JoinedTable('employee', joinToTableOrAlias: 'order', foreignKey: 'services_rep_id', columns: ['employee_name'], alias: 'consultant'),
      ],
      sortFields: [
        SortField('seller', 'employee_name', ascending: false),
        SortField('order', 'order_id', ascending: false),
      ],
      filters: [
        Filter('order', 'order_revenue', 50, comparison: ">="),
      ]
    ));
  }

  @override
  void dispose() {
    // 重要!
    myDizzbaseConnection.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return StreamBuilder<DizzbaseResultRows>(
      stream: _stream_1,
      builder: (context, snapshot) {
        if (snapshot.hasData) {
          // 使用 snapshot.data!.rows![rowNumber][fieldName] 访问数据
          return Text(snapshot.data!.rows![0]['employee_name']);
        } else if (snapshot.hasError) {
          throw Exception("Snapshot has error: ${snapshot.error}");
        } else {
          // 显示进度指示器
          return CircularProgressIndicator();
        }
      },
    );
  }
}

注意:不要在小部件的 build()builder() 方法中创建流,因为这会导致多次创建流(因此性能低下),并且会给服务器带来大量开销。

实时更新基于流的查询

基于流的查询将在查询中的行被更新或删除时自动更新。对于连接表,如果连接表的主键记录插入了新记录,则查询也会更新。例如:

SELECT * FROM orders JOIN customers ON orders.customer_id = customers.id;

在这种情况下,如果为 customers 记录创建了一个新的 orders 行,则查询将被更新。

执行 UPDATE/DELETE/INSERT 事务

使用 DizzbaseUpdate, DizzbaseInsert, DizzbaseDelete 类以及 DizzbaseConnection().updateTransaction(), DizzbaseConnection().insertTransaction(), DizzbaseConnection().deleteTransaction() 方法。返回的结果是一个 Future,要么是 DizzbaseResultRowCount(表示受影响的行数),要么是 DizzbaseResultPkey(表示新行的主键):

// 更新操作,类似 DELETE
DizzbaseConnection().updateTransaction(
  DizzbaseUpdate(table: "employee", fields: ["employee_name", "employee_email"],
    values: [_controllerName.text, _controllerEmail.text], filters: [Filter('employee', 'employee_id', 2)])
).then((result) {
  if (result.error != "") { throw Exception(result.error); }
  setState(() => rowsAffected = result.rowCount);
});

// 插入操作
DizzbaseConnection().insertTransaction(
  DizzbaseInsert(table: "order", fields: ["order_name", "customer_id", "sales_rep_id", "services_rep_id", "order_revenue"],
    values: [_controllerName.text, 1, 2, 2, _controllerRevenue.text], nickName: "InsertOrder")
).then((data) => setState(() => insertedRowPrimaryKey = data.pkey));

更多关于Flutter客户端插件dizzbase_client的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter客户端插件dizzbase_client的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是如何在Flutter项目中集成和使用dizzbase_client插件的一个示例。假设dizzbase_client是一个提供数据库客户端功能的Flutter插件,以下代码将展示如何安装、配置和使用它。

1. 添加依赖

首先,在你的pubspec.yaml文件中添加dizzbase_client依赖:

dependencies:
  flutter:
    sdk: flutter
  dizzbase_client: ^latest_version  # 替换为实际的最新版本号

然后运行flutter pub get来获取依赖。

2. 导入插件

在你的Dart文件中导入dizzbase_client

import 'package:dizzbase_client/dizzbase_client.dart';

3. 初始化客户端

通常,数据库客户端需要一些配置信息来初始化连接。以下是一个假设的初始化过程:

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  // 假设需要一些配置信息来初始化客户端
  final DizzbaseClientConfig config = DizzbaseClientConfig(
    endpoint: 'https://your-database-endpoint.com',
    apiKey: 'your-api-key',
  );

  // 初始化客户端
  DizzbaseClient client = await DizzbaseClient.initialize(config);

  runApp(MyApp(client: client));
}

4. 使用客户端进行数据操作

假设DizzbaseClient提供了基本的CRUD(创建、读取、更新、删除)操作,以下是如何使用这些操作:

class MyApp extends StatelessWidget {
  final DizzbaseClient client;

  MyApp({required this.client});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Dizzbase Client Demo'),
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              ElevatedButton(
                onPressed: () async {
                  // 创建一个新记录
                  Map<String, dynamic> newRecord = {
                    'name': 'John Doe',
                    'email': 'john.doe@example.com',
                  };
                  await client.createRecord('users', newRecord);
                },
                child: Text('Create Record'),
              ),
              ElevatedButton(
                onPressed: () async {
                  // 读取记录
                  List<Map<String, dynamic>> records = await client.readRecords('users');
                  print(records);
                },
                child: Text('Read Records'),
              ),
              ElevatedButton(
                onPressed: () async {
                  // 更新记录
                  Map<String, dynamic> updatedRecord = {
                    'name': 'Jane Doe',
                  };
                  await client.updateRecord('users', 'record-id', updatedRecord); // 替换'record-id'为实际记录ID
                },
                child: Text('Update Record'),
              ),
              ElevatedButton(
                onPressed: () async {
                  // 删除记录
                  await client.deleteRecord('users', 'record-id'); // 替换'record-id'为实际记录ID
                },
                child: Text('Delete Record'),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

注意事项

  1. 错误处理:在实际应用中,你应该添加适当的错误处理来捕获和处理可能出现的异常。
  2. 配置管理:将配置信息(如API密钥和端点)硬编码在应用中通常不是一个好主意。考虑使用环境变量或配置文件来管理这些信息。
  3. 安全性:确保敏感信息(如API密钥)在客户端存储和传输时的安全性。

由于dizzbase_client是一个假设的插件,具体的API和方法可能会有所不同。请参考实际的dizzbase_client文档来获取准确的API信息和用法示例。

回到顶部