Flutter Web端SQLite数据库操作插件sqlite3_web的使用

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

Flutter Web端SQLite数据库操作插件sqlite3_web的使用

sqlite3_web 插件为在Flutter Web项目中使用SQLite数据库提供了支持。通过这个插件,你可以在Web环境中以异步方式访问SQLite数据库。以下是关于如何使用 sqlite3_web 插件的详细说明和一个完整的示例demo。

1. 插件的功能

sqlite3_web 插件主要提供了以下功能:

  • 编写数据库工作者(Workers):你可以使用Dart编写Web Worker来处理数据库操作。
  • 异步接口:插件提供了一个异步接口,用于与SQLite数据库进行交互。
  • 自动选择最佳存储引擎:插件会自动检测浏览器支持的存储API,并选择最适合的存储引擎。

2. 快速开始

2.1 准备工作

  1. 创建数据库控制器:你需要扩展 DatabaseController 类来定义如何打开和管理数据库。例如:
import 'package:sqlite3/sqlite3.dart';
import 'package:sqlite3_web/sqlite3_web.dart';

class ExampleController extends DatabaseController {
  @override
  Future<Database> open(String path, StorageMode storageMode, AccessMode accessMode) async {
    // 打开或创建数据库
    return sqlite3.open(path);
  }

  @override
  void close() {
    // 关闭数据库连接
    database?.close();
  }
}
  1. 定义Worker入口点:你需要为Web Worker定义一个入口点文件,例如 worker.dart,并在其中调用 WebSqlite.workerEntrypoint 方法:
import 'package:sqlite3_web/sqlite3_web.dart';
import 'controller.dart';

void main() {
  WebSqlite.workerEntrypoint(controller: ExampleController());
}
  1. 编译Worker:使用 dart compile js 命令将Worker编译为JavaScript文件。建议使用 -O4 优化选项:
dart compile js -O4 worker.dart -o worker.dart.js
  1. 准备SQLite的WASM模块:你需要一个包含SQLite原生代码的 sqlite3.wasm 文件。你可以从 GitHub Releases 获取预构建版本,或者自己编译。

3. 使用示例

以下是一个完整的示例,展示了如何在Flutter Web项目中使用 sqlite3_web 插件进行数据库操作。

3.1 main.dart 文件

import 'dart:js_interop';
import 'dart:js_interop_unsafe';
import 'package:sqlite3_web/sqlite3_web.dart';

void main() async {
  // 打开SQLite数据库
  final sqlite = await WebSqlite.open(
    worker: Uri.parse('worker.dart.js'),  // Worker文件路径
    wasmModule: Uri.parse('sqlite3.wasm'),  // WASM模块路径
  );

  // 检测可用的功能
  final features = await sqlite.runFeatureDetection();
  print('got features: $features');

  // 连接到推荐的存储引擎
  final connection = await sqlite.connectToRecommended('my_database');
  print(await connection.database.select('select sqlite_version()'));

  // 将数据库操作暴露给JavaScript环境
  globalContext['open'] =
      (JSString name, JSString storage, JSString accessMode) {
    return Future(() async {
      final database = await sqlite.connect(
          name.toDart,
          StorageMode.values.byName(storage.toDart),
          AccessMode.values.byName(accessMode.toDart));

      // 监听数据库更新
      database.updates.listen((update) {
        print('Update on $name: $update');
      });

      return database.toJSBox;
    }).toJS;
  }.toJS;

  // 执行SQL语句
  globalContext['execute'] = (JSBoxedDartObject database, JSString sql) {
    return Future(() async {
      await (database.toDart as Database).execute(sql.toDart);
    }).toJS;
  }.toJS;
}

3.2 worker.dart 文件

import 'package:sqlite3_web/sqlite3_web.dart';
import 'controller.dart';

void main() {
  // 启动Web Worker并传入数据库控制器
  WebSqlite.workerEntrypoint(controller: ExampleController());
}

3.3 controller.dart 文件

import 'package:sqlite3/sqlite3.dart';
import 'package:sqlite3_web/sqlite3_web.dart';

class ExampleController extends DatabaseController {
  @override
  Future<Database> open(String path, StorageMode storageMode, AccessMode accessMode) async {
    // 打开或创建数据库
    return sqlite3.open(path);
  }

  @override
  void close() {
    // 关闭数据库连接
    database?.close();
  }
}

4. 自定义请求

在某些情况下,你可能希望重用 sqlite3_web 创建的Worker通信机制来实现自定义功能。例如,你可以使用共享Worker让不同的标签页连接到同一个数据库实例。为此,你可以在 WorkerDatabase 中重写 handleCustomRequest 方法,以实现同步原语或其他自定义逻辑。

客户端可以通过 Database.customRequest 发送自定义请求。例如:

final response = await database.customRequest({
  'type': 'custom_request',
  'data': 'some_data'
});
print(response);

更多关于Flutter Web端SQLite数据库操作插件sqlite3_web的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter Web端SQLite数据库操作插件sqlite3_web的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是一个关于如何在Flutter Web端使用sqlite3_web插件进行SQLite数据库操作的代码示例。sqlite3_web是一个允许在Flutter Web应用中操作SQLite数据库的插件。需要注意的是,由于Flutter Web的运行环境与原生环境不同,数据库操作可能会受到一些限制,并且通常数据会存储在浏览器的IndexedDB中。

首先,确保你的pubspec.yaml文件中已经添加了sqlite3_web依赖:

dependencies:
  flutter:
    sdk: flutter
  sqlite3_web: ^x.y.z  # 替换为最新版本号

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

接下来是一个简单的示例,展示了如何在Flutter Web应用中使用sqlite3_web进行数据库操作:

import 'package:flutter/material.dart';
import 'package:sqlite3_web/sqlite3_web.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Web SQLite3 Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  Database? _db;

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

  Future<void> _openDatabase() async {
    // 打开(或创建)数据库
    _db = await openDatabase(
      'demo.db',
      version: 1,
      onOpen: (db) {
        print('Database opened');
      },
      onCreate: (db, version) async {
        // 创建表
        await db.execute(
          'CREATE TABLE IF NOT EXISTS users ('
          'id INTEGER PRIMARY KEY AUTOINCREMENT,'
          'name TEXT NOT NULL,'
          'age INTEGER NOT NULL'
          ')',
        );
        print('Table created');
      },
      onUpgrade: (db, oldVersion, newVersion) async {
        // 数据库升级逻辑
        await db.execute('DROP TABLE IF EXISTS users');
        await onCreate(db, newVersion);
        print('Database upgraded');
      },
    );
  }

  Future<void> _insertData() async {
    if (_db != null) {
      await _db!.insert(
        'users',
        {
          'name': 'Alice',
          'age': 30,
        },
        conflictAlgorithm: ConflictAlgorithm.replace,
      );
      print('Data inserted');
    }
  }

  Future<List<Map<String, dynamic>>> _queryData() async {
    if (_db != null) {
      return await _db!.query('users');
    } else {
      return [];
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter Web SQLite3 Demo'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            ElevatedButton(
              onPressed: () async {
                await _insertData();
                setState(() {}); // 触发UI更新(如果需要)
              },
              child: Text('Insert Data'),
            ),
            SizedBox(height: 20),
            ElevatedButton(
              onPressed: () async {
                List<Map<String, dynamic>> users = await _queryData();
                print('Query Result: $users');
                // 这里可以更新UI来显示查询结果
              },
              child: Text('Query Data'),
            ),
          ],
        ),
      ),
    );
  }
}

在这个示例中,我们:

  1. 使用openDatabase函数打开(或创建)一个名为demo.db的数据库。
  2. onCreate回调中创建了一个名为users的表。
  3. 提供了_insertData函数来向users表中插入数据。
  4. 提供了_queryData函数来查询users表中的所有数据。
  5. 在UI中提供了两个按钮,一个用于插入数据,另一个用于查询数据。

请注意,由于Flutter Web的限制,SQLite数据库实际上是通过IndexedDB在浏览器中实现的,因此性能可能与原生环境有所不同。此外,对于更复杂的应用,可能需要考虑使用更高级的持久化解决方案,如Firebase Firestore或Amplify DataStore等。

回到顶部