Flutter异步SQLite数据库管理插件drift_sqlite_async的使用

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

Flutter异步SQLite数据库管理插件drift_sqlite_async的使用

drift_sqlite_async 是一个允许在sqlite_async数据库上使用Drift的Flutter插件。它使得两种API可以在同一应用程序中无缝协作。以下是该插件的主要功能和用法。

功能支持

  1. 查询操作:包括select、insert、update、delete在内的所有SQL查询。
  2. 事务处理:支持事务及其嵌套。
  3. 表更新同步:sqlite_async与Drift之间的表更新会相互传播,无论使用哪种API,查询监控都能正常工作。
  4. 并发执行:选择查询可以与写入和其他选择语句并行运行。
  5. 迁移支持(可选):支持Drift的数据库结构迁移。

使用方法

创建数据库连接

要将sqlite_async的SqliteDatabase转换为Drift可用的DatabaseConnection或QueryExecutor,请使用SqliteAsyncDriftConnection

@DriftDatabase(tables: [TodoItems])
class AppDatabase extends _$AppDatabase {
  AppDatabase(SqliteConnection db) : super(SqliteAsyncDriftConnection(db));

  @override
  int get schemaVersion => 1;
}

Future<void> main() async {
  // sqlite_async数据库实例
  final db = SqliteDatabase(path: 'example.db');
  // Drift数据库实例
  final appdb = AppDatabase(db);
}

完整示例代码

下面是一个完整的示例,演示了如何创建表格、插入数据、监听变化以及关闭数据库连接。

import 'package:drift/drift.dart';
import 'package:drift_sqlite_async/drift_sqlite_async.dart';
import 'package:sqlite_async/sqlite_async.dart';

part 'main.g.dart';

// 定义表格结构
class TodoItems extends Table {
  @override
  String get tableName => 'todos';

  IntColumn get id => integer().autoIncrement()();
  TextColumn get description => text()();
}

// 定义数据库类
@DriftDatabase(tables: [TodoItems])
class AppDatabase extends _$AppDatabase {
  AppDatabase(SqliteConnection db) : super(SqliteAsyncDriftConnection(db));

  @override
  int get schemaVersion => 1;
}

Future<void> main() async {
  // 初始化sqlite_async数据库
  final db = SqliteDatabase(path: 'example.db');

  // 手动管理schema
  await db.execute(
      'CREATE TABLE IF NOT EXISTS todos(id INTEGER PRIMARY KEY, description TEXT)');

  // 初始化Drift数据库
  final appdb = AppDatabase(db);

  // 监听todo列表的变化
  appdb.select(appdb.todoItems).watch().listen((todos) {
    print('Todos: $todos');
  });

  // 使用Drift插入数据
  await appdb.into(appdb.todoItems).insert(
        TodoItemsCompanion.insert(description: 'Test Drift'),
      );

  // 使用sqlite_async直接插入数据
  await db.execute('INSERT INTO todos(description) VALUES(?)', ['Test Direct']);

  // 等待一段时间以确保监听器捕获到变化
  await Future.delayed(const Duration(milliseconds: 100));

  // 关闭数据库连接
  await appdb.close();
  await db.close();
}

事务与并发

  • sqlite_async 默认使用WAL模式,并允许多个读取连接,这在与Drift一起使用时同样适用。
  • Drift的事务使用sqlite_asyncwriteTransaction,共享相同的锁机制来防止冲突。
  • 当前不支持只读事务。
  • 支持嵌套事务,通过SAVEPOINT实现。
  • Drift的选择语句使用sqlite_async中的读操作(getAll()), 并且可以与写入和其他选择语句并行执行。

更新通知

sqlite_async 使用SQLite的update_hook来检测更改,自动拾取由Drift做出的任何修改。这意味着即使是在Drift中执行的自定义查询也会触发更新事件。此外,从sqlite_async来的更新也会被传播到Drift,只要没有活跃的写入事务。需要注意的是,在某些情况下可能会出现重复事件,但这通常不会对大多数应用产生重大影响。

Web支持

Web端的支持目前处于Beta阶段,需要Sqlite3 WASM和web worker JavaScript文件。这些文件应该放在项目的web/目录下。具体步骤请参考官方文档或GitHub上的发布页面获取最新的编译好的worker文件和WASM资源。


以上就是关于drift_sqlite_async插件的基本介绍及使用方法。如果你有更多问题或者遇到困难,欢迎继续提问!


更多关于Flutter异步SQLite数据库管理插件drift_sqlite_async的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter异步SQLite数据库管理插件drift_sqlite_async的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,下面是一个关于如何在Flutter项目中使用drift_sqlite_async插件进行异步SQLite数据库管理的代码示例。drift_sqlite_async是一个强大的Flutter插件,它允许你在Flutter应用中以异步方式管理SQLite数据库。

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

dependencies:
  flutter:
    sdk: flutter
  drift: ^x.y.z  # 确保使用最新版本
  drift_sqlite_async: ^x.y.z  # 确保使用最新版本

替换^x.y.z为实际的最新版本号。

接下来,你需要定义你的数据库模式。这里是一个简单的示例,包含一个用户表:

// lib/data/database.dart

import 'package:drift/drift.dart';

part 'database.g.dart';

@DriftData(tables: [Users])
class MyDatabase extends _$MyDatabase {}

class Users extends Table {
  IntColumn get id => integer().autoIncrement().primaryKey()();
  TextColumn get name => text().withDefault('Unknown')();
  TextColumn get email => text().nullable()();
}

运行flutter pub getflutter pub run build_runner build来生成数据库代码。

然后,你可以创建一个数据库服务类来管理数据库操作:

// lib/data/database_service.dart

import 'package:drift/drift.dart';
import 'package:drift_sqlite_async/drift_sqlite_async.dart';
import 'database.dart';

class DatabaseService {
  late final MyDatabase _db;

  DatabaseService() {
    // 初始化数据库连接
    final database = NativeDatabase.memory(); // 使用内存数据库,也可以传入文件路径
    _db = MyDatabase(database);
    _db.createAllTables(); // 创建所有表
  }

  // 异步插入用户
  Future<void> insertUser(String name, String? email) async {
    final user = Users.insert(
      name: name,
      email: email,
    );
    await _db.withTransaction((transaction) async {
      await transaction.insert(user);
    });
  }

  // 异步查询所有用户
  Future<List<UsersRow>> getAllUsers() async {
    return await _db.query(Users).getAll();
  }
}

UsersRowdrift自动生成的,对应于Users表的行对象。

最后,在你的Flutter应用中使用这个服务:

// lib/main.dart

import 'package:flutter/material.dart';
import 'data/database_service.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  final DatabaseService databaseService = DatabaseService();

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('Drift SQLite Async Example')),
        body: FutureBuilder<List<UsersRow>>(
          future: databaseService.getAllUsers(),
          builder: (context, snapshot) {
            if (snapshot.connectionState == ConnectionState.waiting) {
              return Center(child: CircularProgressIndicator());
            } else if (snapshot.hasError) {
              return Center(child: Text('Error: ${snapshot.error!}'));
            } else {
              final users = snapshot.data ?? [];
              return ListView.builder(
                itemCount: users.length,
                itemBuilder: (context, index) {
                  final user = users[index];
                  return ListTile(
                    title: Text('${user.name} (${user.email ?? 'No Email'})'),
                  );
                },
              );
            }
          },
        ),
        floatingActionButton: FloatingActionButton(
          onPressed: () async {
            await databaseService.insertUser('New User', 'newuser@example.com');
            // 重新获取用户列表以显示新插入的用户
            setState(() {}); // 注意:这里需要在一个StatefulWidget中使用
          },
          tooltip: 'Add User',
          child: Icon(Icons.add),
        ),
      ),
    );
  }
}

注意:上面的setState调用在一个StatelessWidget中是不允许的。为了简化示例,我直接在MyApp中使用了它。在实际应用中,你应该将数据库逻辑和UI状态管理放在一个StatefulWidget中。

这个示例展示了如何使用drift_sqlite_async插件在Flutter中进行异步SQLite数据库管理,包括定义数据库模式、插入数据和查询数据。希望这对你有所帮助!

回到顶部