Flutter异步SQLite数据库操作插件sqlite_async的使用

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

Flutter异步SQLite数据库操作插件sqlite_async的使用

介绍

sqlite_async 是一个高性能的异步接口,用于在Dart和Flutter中操作SQLite。SQLite以其小巧、快速以及丰富的内置功能著称,非常适合用作应用程序内的数据库。然而,为了达到最佳性能,SQLite需要根据不同的应用场景进行配置。sqlite3 Dart绑定提供了直接同步访问SQLite数据库的能力,但将配置留给开发者完成。

sqlite_async库包装了这些绑定,并为数据库配置了一套良好的默认设置,所有数据库调用都是异步的以避免阻塞UI,同时仍然提供直接的SQL查询访问。

特性

  • 所有操作默认情况下都是异步的 - 不会阻塞主线程。
  • 可以监听查询,在底层数据变化时自动重新运行。
  • 默认支持并发事务 - 支持一个写入事务和多个读取事务。
  • 使用WAL模式实现快速写入,并允许读取事务与写入事务并发执行。
  • 在隔离区中支持直接同步访问,适用于性能敏感的使用场景。
  • 自动转换查询参数为JSON(如果适用),简化JSON1操作。
  • 直接的SQL查询 - 不需要包装类或代码生成。

有关这些特性重要性的详细解释,请参阅此博客文章

安装

对于Flutter应用,您可以通过以下命令安装sqlite_async

dart pub add sqlite_async

并且还需要添加sqlite3_flutter_libs来包含原生的SQLite库。

对于其他平台的支持情况,请查阅sqlite3包文档

注意:Web平台当前不被支持。

快速开始

下面是一个简单的例子,演示如何使用sqlite_async创建表、插入数据、查询数据以及关闭数据库连接。

import 'package:sqlite_async/sqlite_async.dart';

void main() async {
  // 定义迁移脚本
  final migrations = SqliteMigrations()
    ..add(SqliteMigration(1, (tx) async {
      await tx.execute(
          'CREATE TABLE test_data(id INTEGER PRIMARY KEY AUTOINCREMENT, data TEXT)');
    }));

  // 打开数据库
  final db = SqliteDatabase(path: 'test.db');
  
  // 运行迁移
  await migrations.migrate(db);

  // 插入多条记录
  await db.executeBatch('INSERT INTO test_data(data) values(?)', [
    ['Test1'],
    ['Test2']
  ]);

  // 查询所有记录
  var results = await db.getAll('SELECT * FROM test_data');
  print('Results: $results');

  // 在单个写入事务中组合多个语句
  await db.writeTransaction((tx) async {
    await tx.execute('INSERT INTO test_data(data) values(?)', ['Test3']);
    await tx.execute('INSERT INTO test_data(data) values(?)', ['Test4']);
  });

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

Web支持

Web平台的支持目前处于测试阶段。要在Web上使用sqlite_async,你需要确保Sqlite3 WASM和web worker Javascript文件可以通过可配置的URI访问。

例如:

import 'package:sqlite_async/sqlite_async.dart';

final db = SqliteDatabase(
    path: 'test.db',
    options: SqliteOptions(
        webSqliteOptions: WebSqliteOptions(
            wasmUri: 'sqlite3.wasm', workerUri: 'db_worker.js')));

更多示例代码可以参考项目仓库中的不同示例文件,包括基本设置、监听查询、数据库迁移等。

希望以上信息能够帮助你理解并使用sqlite_async插件!如果有任何问题或需要进一步的帮助,请随时提问。


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

1 回复

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


当然,以下是如何在Flutter中使用sqlite_async插件进行异步SQLite数据库操作的示例代码。这个插件允许你以异步方式执行SQLite数据库操作,从而提高应用的性能和响应性。

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

dependencies:
  flutter:
    sdk: flutter
  sqlite_async: ^0.5.0  # 请检查最新版本号

然后,运行flutter pub get来安装依赖。

接下来,我们编写一些代码来演示如何使用sqlite_async进行数据库操作。

1. 初始化数据库和表

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('SQLite Async Example'),
        ),
        body: DatabaseExample(),
      ),
    );
  }
}

class DatabaseExample extends StatefulWidget {
  @override
  _DatabaseExampleState createState() => _DatabaseExampleState();
}

class _DatabaseExampleState extends State<DatabaseExample> {
  late DatabaseConnection _db;

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

  Future<void> _initializeDatabase() async {
    _db = await DatabaseConnection.create(
      'my_database.db',
      version: 1,
      onCreate: (Database db, int version, String? name) async {
        await db.execute('CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)');
      },
      onUpgrade: (Database db, int oldVersion, int newVersion, String? name) async {
        await db.execute('DROP TABLE IF EXISTS users');
        await db.execute('CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)');
      },
      onDowngrade: (Database db, int oldVersion, int newVersion, String? name) async {
        // Handle downgrade if needed
      },
      onOpen: (Database db) async {
        // Do something when the database is opened
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: ElevatedButton(
        onPressed: () => _insertData(),
        child: Text('Insert Data'),
      ),
    );
  }

  Future<void> _insertData() async {
    await _db.transaction((txn) async {
      await txn.execute(
        'INSERT INTO users (name) VALUES (?)',
        ['John Doe'],
      );
    });
    print('Data inserted');
  }
}

2. 查询数据

你可以通过以下方式查询数据:

Future<List<Map<String, dynamic>>> _queryData() async {
  List<Map<String, dynamic>> results = await _db.query('users', columns: ['*']);
  return results;
}

你可以在按钮点击或其他事件触发时调用这个函数,并处理查询结果。例如:

ElevatedButton(
  onPressed: async () {
    List<Map<String, dynamic>> users = await _queryData();
    print('Users: $users');
  },
  child: Text('Query Data'),
),

3. 更新数据

更新数据可以使用update方法:

Future<void> _updateData() async {
  await _db.transaction((txn) async {
    await txn.execute(
      'UPDATE users SET name = ? WHERE id = ?',
      ['Jane Doe', 1],
    );
  });
  print('Data updated');
}

4. 删除数据

删除数据可以使用delete方法:

Future<void> _deleteData() async {
  await _db.transaction((txn) async {
    await txn.execute(
      'DELETE FROM users WHERE id = ?',
      [1],
    );
  });
  print('Data deleted');
}

完整示例

将上述所有部分整合到一个完整的示例中:

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('SQLite Async Example'),
        ),
        body: Padding(
          padding: const EdgeInsets.all(16.0),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              ElevatedButton(
                onPressed: () => _insertData(),
                child: Text('Insert Data'),
              ),
              ElevatedButton(
                onPressed: async () {
                  List<Map<String, dynamic>> users = await _queryData();
                  print('Users: $users');
                },
                child: Text('Query Data'),
              ),
              ElevatedButton(
                onPressed: () => _updateData(),
                child: Text('Update Data'),
              ),
              ElevatedButton(
                onPressed: () => _deleteData(),
                child: Text('Delete Data'),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

class DatabaseHelper {
  late DatabaseConnection _db;

  DatabaseHelper() {
    _initializeDatabase();
  }

  Future<void> _initializeDatabase() async {
    _db = await DatabaseConnection.create(
      'my_database.db',
      version: 1,
      onCreate: (Database db, int version, String? name) async {
        await db.execute('CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)');
      },
      onUpgrade: (Database db, int oldVersion, int newVersion, String? name) async {
        await db.execute('DROP TABLE IF EXISTS users');
        await db.execute('CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)');
      },
    );
  }

  Future<void> _insertData() async {
    await _db.transaction((txn) async {
      await txn.execute(
        'INSERT INTO users (name) VALUES (?)',
        ['John Doe'],
      );
    });
  }

  Future<List<Map<String, dynamic>>> _queryData() async {
    List<Map<String, dynamic>> results = await _db.query('users', columns: ['*']);
    return results;
  }

  Future<void> _updateData() async {
    await _db.transaction((txn) async {
      await txn.execute(
        'UPDATE users SET name = ? WHERE id = ?',
        ['Jane Doe', 1],
      );
    });
  }

  Future<void> _deleteData() async {
    await _db.transaction((txn) async {
      await txn.execute(
        'DELETE FROM users WHERE id = ?',
        [1],
      );
    });
  }
}

class _MyAppState extends State<MyApp> {
  late DatabaseHelper dbHelper = DatabaseHelper();

  @override
  Widget build(BuildContext context) {
    // Build UI as shown above
  }
}

// Note: You need to adjust the state management part to use the DatabaseHelper instance correctly.

请注意,上述代码示例中的DatabaseHelper类被创建但并未在UI组件中直接使用,因为示例中直接使用了匿名函数。在实际应用中,你可能需要将数据库操作封装到服务类中,并通过状态管理(如Provider、Riverpod等)在UI组件中调用这些服务。

回到顶部