Flutter数据库工具插件dbutils的使用

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

Flutter数据库工具插件dbutils的使用

简介

dbutils 是一个用于Flutter应用程序中操作SQLite数据库的Dart包。它与sqflite插件协同工作,简化了对SQLite数据库的操作流程。本文将详细介绍如何安装、配置和使用dbutils进行数据库操作,并提供完整的示例代码。

安装

pubspec.yaml文件中添加以下依赖项:

dependencies:
  dbutils:^5.0.0

确保版本号遵循语义化版本控制规范,即主要版本号后跟随两个零(如^5.0.0),以便接收次要版本更新带来的新特性或补丁修复。

数据库表定义

Employee类为例,该类继承自DBInterface并实现了三个必需属性:name(数据库名称)、version(数据库版本)和onCreate()方法(创建数据库时执行)。以下是Employee.dart文件的部分代码片段:

import 'package:dbutils/dbutils.dart';

class Employee extends DBInterface {
  static final String tableName = 'employee';
  
  // 单例模式
  static late Employee _this;
  factory Employee() {
    if (_this == null) {
      _this = Employee._();
      _this.name = 'employees.db';
      _this.version = 1;
    }
    return _this;
  }

  Employee._();

  @override
  Future<void> onCreate(Database db, int version) async {
    await db.execute('''
      CREATE TABLE $tableName (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        firstName TEXT,
        lastName TEXT,
        position TEXT
      )
    ''');
  }

  // 添加员工记录
  Future<int> addEmployee(Map<String, dynamic> employee) async {
    return await saveRec(employee, tableName);
  }

  // 删除员工记录
  Future<int> deleteEmployee(int id) async {
    return await deleteRec({'id': id}, tableName);
  }

  // 获取所有员工记录
  Future<List<Map<String, dynamic>>> getEmployees() async {
    return await rawQuery('SELECT * FROM $tableName');
  }
}

示例应用

主程序入口

main.dart是应用程序的入口点,负责启动Material风格的应用程序并导航到员工列表页面。

import 'package:flutter/material.dart';
import 'src/employee_list.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) => MaterialApp(
        title: 'DBUtils Demo app',
        theme: ThemeData(
          primarySwatch: Colors.blue,
        ),
        home: const EmployeeList(key: Key('EmployeeList')),
      );
}

员工列表页面

EmployeeList.dart展示了从数据库中检索到的所有员工信息,并允许用户添加新员工或查看详情。

import 'package:flutter/material.dart';
import 'employee.dart';
import 'employee_detail.dart';

class EmployeeList extends StatefulWidget {
  const EmployeeList({Key? key}) : super(key: key);

  @override
  State createState() => _EmployeeListState();
}

class _EmployeeListState extends State<EmployeeList> {
  final Employee _employee = Employee();

  @override
  void initState() {
    super.initState();
    _employee.init(); // 初始化数据库连接
  }

  @override
  void dispose() {
    _employee.dispose(); // 关闭数据库连接
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Employees'),
      ),
      body: FutureBuilder<List<Map<String, dynamic>>>(
        future: _employee.getEmployees(),
        builder: (context, snapshot) {
          if (!snapshot.hasData) return const Center(child: CircularProgressIndicator());
          final employees = snapshot.data!;
          return ListView.builder(
            itemCount: employees.length,
            itemBuilder: (context, index) {
              final employee = employees[index];
              return ListTile(
                title: Text('${employee['firstName']} ${employee['lastName']}'),
                subtitle: Text(employee['position']),
                onTap: () {
                  Navigator.push(
                    context,
                    MaterialPageRoute(
                      builder: (_) => EmployeeDetail(employee: employee),
                    ),
                  );
                },
              );
            },
          );
        },
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          Navigator.push(
            context,
            MaterialPageRoute(
              builder: (_) => EmployeeDetail(),
            ),
          );
        },
        child: const Icon(Icons.add),
      ),
    );
  }
}

员工详情页面

EmployeeDetail.dart用于展示单个员工的具体信息,同时支持编辑和保存更改。

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

class EmployeeDetail extends StatefulWidget {
  final Map<String, dynamic>? employee;

  const EmployeeDetail({Key? key, this.employee}) : super(key: key);

  @override
  State createState() => _EmployeeDetailState();
}

class _EmployeeDetailState extends State<EmployeeDetail> {
  final Employee _employee = Employee();
  final TextEditingController _firstNameController = TextEditingController();
  final TextEditingController _lastNameController = TextEditingController();
  final TextEditingController _positionController = TextEditingController();

  @override
  void initState() {
    super.initState();
    if (widget.employee != null) {
      _firstNameController.text = widget.employee!['firstName'];
      _lastNameController.text = widget.employee!['lastName'];
      _positionController.text = widget.employee!['position'];
    }
  }

  void _submit() async {
    final Map<String, dynamic> employee = {
      'firstName': _firstNameController.text,
      'lastName': _lastNameController.text,
      'position': _positionController.text,
    };

    if (widget.employee != null) {
      employee['id'] = widget.employee!['id'];
    }

    try {
      bool success = await _employee.save(employee, 'employee');
      if (success) {
        ScaffoldMessenger.of(context).showSnackBar(
          const SnackBar(content: Text('Saved successfully')),
        );
        Navigator.pop(context);
      } else {
        ScaffoldMessenger.of(context).showSnackBar(
          const SnackBar(content: Text('Failed to save')),
        );
      }
    } catch (e) {
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text('Error: $e')),
      );
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Employee Detail'),
        actions: [
          IconButton(
            icon: const Icon(Icons.delete),
            onPressed: () async {
              if (widget.employee != null) {
                try {
                  await _employee.deleteEmployee(widget.employee!['id']);
                  ScaffoldMessenger.of(context).showSnackBar(
                    const SnackBar(content: Text('Deleted successfully')),
                  );
                  Navigator.pop(context);
                } catch (e) {
                  ScaffoldMessenger.of(context).showSnackBar(
                    SnackBar(content: Text('Error: $e')),
                  );
                }
              }
            },
          ),
        ],
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          children: [
            TextField(
              controller: _firstNameController,
              decoration: const InputDecoration(labelText: 'First Name'),
            ),
            TextField(
              controller: _lastNameController,
              decoration: const InputDecoration(labelText: 'Last Name'),
            ),
            TextField(
              controller: _positionController,
              decoration: const InputDecoration(labelText: 'Position'),
            ),
            ElevatedButton(
              onPressed: _submit,
              child: const Text('Save'),
            ),
          ],
        ),
      ),
    );
  }
}

通过上述步骤,您可以快速上手dbutils插件,在Flutter项目中实现对SQLite数据库的基本CRUD操作。希望这份指南能帮助您更好地理解和使用dbutils。如果有任何问题或需要进一步的帮助,请随时查阅官方文档或访问GitHub仓库获取更多信息。


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

1 回复

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


当然,以下是一个关于如何在Flutter项目中使用dbutils插件进行数据库操作的示例。dbutils是一个简化SQLite数据库操作的Flutter插件。请确保你已经将dbutils添加到了你的pubspec.yaml文件中:

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

1. 初始化数据库

首先,在你的Flutter应用中初始化数据库。这通常在应用启动时进行。

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

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

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

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

class _MyHomePageState extends State<MyHomePage> {
  late DatabaseHelper _dbHelper;

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

  void initDatabase() async {
    _dbHelper = await DatabaseHelper.getInstance("my_database.db");
    // 可选:创建表
    await _dbHelper.createTable(
      tableName: "users",
      columns: [
        Column("id", "INTEGER", isPrimaryKey: true, autoGenerate: true),
        Column("name", "TEXT", isNotNull: true),
        Column("email", "TEXT", isUnique: true, isNotNull: true),
      ],
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Flutter DBUtils Demo"),
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            // 示例:插入数据
            insertData();
          },
          child: Text("Insert Data"),
        ),
      ),
    );
  }

  void insertData() async {
    await _dbHelper.insert(
      tableName: "users",
      data: {
        "name": "John Doe",
        "email": "john@example.com",
      },
    );
    print("Data inserted");
  }
}

2. 创建DatabaseHelper类

DatabaseHelper类封装了与数据库交互的逻辑。这个类使用dbutils提供的API来创建实例、创建表、插入数据等。

import 'package:dbutils/dbutils.dart';

class DatabaseHelper {
  late Database? _db;

  DatabaseHelper._();

  static late DatabaseHelper _instance;

  static Future<DatabaseHelper> getInstance(String dbName) async {
    if (_instance == null) {
      _instance = DatabaseHelper._();
      _instance._db = await DbUtils.openDatabase(dbName);
    }
    return _instance;
  }

  Future<void> createTable({
    required String tableName,
    required List<Column> columns,
  }) async {
    String createTableSql = "CREATE TABLE IF NOT EXISTS $tableName (${columns.map((column) => "${column.name} ${column.type} ${column.toSqlConstraints()}").join(", ")})";
    await _db!.rawQuery(createTableSql);
  }

  Future<void> insert({
    required String tableName,
    required Map<String, dynamic> data,
  }) async {
    String insertSql = "INSERT INTO $tableName (${data.keys.join(", ")}) VALUES (${data.values.map((value) => if (value is String) "'$value'" else value.toString()).join(", ")})";
    await _db!.rawInsert(insertSql);
  }
}

class Column {
  String name;
  String type;
  bool? isPrimaryKey;
  bool? isNotNull;
  bool? isUnique;
  bool? autoGenerate;

  Column(this.name, this.type, {this.isPrimaryKey, this.isNotNull, this.isUnique, this.autoGenerate});

  String toSqlConstraints() {
    List<String> constraints = [];
    if (isPrimaryKey == true) constraints.add("PRIMARY KEY");
    if (isNotNull == true) constraints.add("NOT NULL");
    if (isUnique == true) constraints.add("UNIQUE");
    if (autoGenerate == true) constraints.add("AUTOINCREMENT");
    return constraints.join(" ");
  }
}

3. 运行应用

现在,你可以运行你的Flutter应用。点击按钮后,它将创建一个名为users的表,并插入一条数据。

注意事项

  • 确保你已经正确添加了dbutils依赖并运行了flutter pub get
  • 这个示例仅展示了基本的数据库操作。对于更复杂的查询和事务处理,你可以查阅dbutils的官方文档。
  • 在实际应用中,考虑添加错误处理和日志记录,以提高应用的健壮性和可维护性。
回到顶部