Flutter数据库操作看这一篇就够了

news2024/11/22 5:07:38

文章目录

  • Flutter常用数据库操作库
  • 最常用的sqflite介绍
    • 简介
    • 举例
  • 依赖sqflite,单例模式封装一个sqlite操作类
  • 说明
    • initDb说明
    • conflictAlgorithm说明

Flutter常用数据库操作库

Flutter是一种跨平台的移动应用程序开发框架,支持使用多种类型的数据库进行数据存储和管理。Flutter中使用数据库通常需要依赖第三方库来实现,以下是一些常用的Flutter数据库库:

  • sqflite:是一个SQLite数据库的Flutter插件,提供了类似于Android中SQLite的API接口,支持基本的CRUD操作。
  • firebase_database:是谷歌提供的一种实时的NoSQL数据库,可用于Flutter应用程序的数据存储和同步。
  • hive:是一种快速、轻量级的键值对数据库,具有高性能和低延迟的特点,适用于Flutter应用程序中的本地数据存储。

最常用的sqflite介绍

简介

sqflite是一个SQLite数据库的Flutter插件,提供了类似于Android中SQLite的API接口,支持基本的CRUD操作。它是Flutter中使用最广泛的本地数据库库之一,可用于存储应用程序的本地数据。sqflite具有轻量级、高性能和易于使用的特点,适合于小型应用程序或需要简单本地数据存储的应用程序。

举例

下面是一个使用sqflite库的示例代码,演示如何在Flutter应用程序中创建和使用SQLite数据库:

  1. 添加sqflite库的依赖:

在Flutter项目的pubspec.yaml文件中添加sqflite库的依赖:

dependencies:
  sqflite: ^2.2.8+4
  1. 创建数据库:

在Flutter应用程序中创建一个数据库示例,可以通过执行以下代码来创建一个名为my_database.db的SQLite数据库:

import 'package:sqflite/sqflite.dart';
import 'package:path/path.dart';

class MyDatabase {
  static final MyDatabase _instance = MyDatabase._internal();

  factory MyDatabase() => _instance;

  static Database _database;

  MyDatabase._internal();

  Future<Database> get database async {
    if (_database != null) return _database;

    _database = await _initDatabase();
    return _database;
  }

  Future<Database> _initDatabase() async {
    final dbPath = await getDatabasesPath();
    final path = join(dbPath, 'my_database.db');

    return await openDatabase(
      path,
      version: 1,
      onCreate: (db, version) async {
        await db.execute(
          'CREATE TABLE users(id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT)',
        );
      },
    );
  }
}

在上述代码中,我们使用了sqflite库中的openDatabase方法来创建数据库并指定数据库文件路径。我们还提供了一个onCreate回调函数,在创建数据库时执行一些初始化操作,例如创建表等。

  1. 插入数据:

下面是一个示例代码,演示如何向数据库中插入一条数据:

final db = await MyDatabase().database;
await db.insert(
  'users',
  {'name': 'John'},
  conflictAlgorithm: ConflictAlgorithm.replace,
);

在上述代码中,我们首先获取了一个数据库实例,然后使用insert方法向名为users的表中插入一条数据。我们将数据存储为一个Map对象,其中键为列名,值为要插入的值。如果表中已经有相同主键的记录,我们使用conflictAlgorithm参数指定了冲突处理策略,这里使用了ConflictAlgorithm.replace,表示用新数据替换旧数据。

  1. 查询数据:

下面是一个示例代码,演示如何从数据库中查询数据:

final db = await MyDatabase().database;
final List<Map<String, dynamic>> users = await db.query('users');

在上述代码中,我们首先获取了一个数据库实例,然后使用query方法查询名为users的表中的所有数据。查询结果将返回一个包含多个Map对象的列表,其中每个Map对象表示一条记录,键为列名,值为对应的值。

  1. 更新数据:

下面是一个示例代码,演示如何更新数据库中的数据:

final db = await MyDatabase().database;
await db.update(
  'users',
  {'name': 'Mary'},
  where: 'id = ?',
  whereArgs: [1],
);

在上述代码中,我们首先获取了一个数据库实例,然后使用update方法更新名为users的表中的一条数据。我们使用where参数指定了要更新的记录的条件,这里表示id为1,使用whereArgs参数指定了条件中的参数值。我们将要更新的数据存储为一个Map对象,其中键为列名,值为要更新的值。

  1. 删除数据:

下面是一个示例代码,演示如何从数据库中删除数据:

final db = await MyDatabase().database;
await db.delete(
  'users',
  where: 'id = ?',
  whereArgs: [1],
);

在上述代码中,我们首先获取了一个数据库实例,然后使用delete方法删除名为users的表中的一条数据。我们使用where参数指定了要删除的记录的条件,这里表示id为1,使用whereArgs参数指定了条件中的参数值。

依赖sqflite,单例模式封装一个sqlite操作类

import 'package:path/path.dart';
import 'package:path_provider/path_provider.dart';
import 'package:sqflite/sqflite.dart';
import 'package:learning/model/task_model.dart';

class DatabaseHelper {
  DatabaseHelper._(); //单例模式

  static final DatabaseHelper db = DatabaseHelper._();
  static Database? _database;

  Future<Database?> get database async {
    _database ??= await initDb();
    return _database;
  }

  //init database and open it
  Future<Database> initDb() async {
    print("initDb");
    Directory documentDirectory = await getApplicationDocumentsDirectory();
    String path = join(documentDirectory.path, 'yytimer.db');
    print("initDb ${path}");

    Database db = await openDatabase(path, version: 1, onOpen: (db) async {
      // 等待表创建完成
      await db.execute(
          'CREATE TABLE IF NOT EXISTS timerdata (id INTEGER PRIMARY KEY, title TEXT, sptime INTEGER, retime INTEGER, cycle INTEGER, setsgap INTEGER, groups INTEGER)');
    });
    return db;
  }

  //insert database
  Future<int?> insert(Task task) async {
    print('insert data Saving Task...');
    final db = await database; // 确保database在上下文中定义

    try {
      var result = await db?.rawInsert(
          'INSERT OR REPLACE INTO timerdata (id,title,sptime,retime, cycle,setsgap,groups) VALUES (?,?,?,?,?,?,?)',
          [
            task.id,
            task.title,
            task.sptime,
            task.retime,
            task.cycle,
            task.setsgap,
            task.groups
          ]);
      print('insert data id timerdata saved! ${task.id}, ${task.title}, ${task.sptime}, ${task.retime},${task.cycle}, ${task.setsgap}, ${task.groups}');
      return result;
    } on DatabaseException catch (e) {
      print(e);
      return -1;
    }
  }

  //query database
  Future<List<Task>> getAll() async {
    print('getAll database...');
    var db = await database;
    var query = await db?.query('timerdata', orderBy: 'id DESC');

    List<Task> tasks =
        query!.isNotEmpty ? query.map((t) => Task.fromMap(t)).toList() : [];
    print('getAll in database: ${tasks.length} , ${tasks[0].title},${tasks[1].title}');
    return tasks;
  }

  //delete sql by id
  Future<void> delete(int id) async {
    var db = await database;
    await db?.rawDelete('DELETE FROM timerdata WHERE id = ?', [id]);
  }

  //delete sql by title
  Future<void> deleteByTitle(String title) async {
    var db = await database;
    await db?.rawDelete('DELETE FROM timerdata WHERE title = ?', [title]);
  }

  //update database by id
  Future<void> updateDatabase(Task task) async {
    final db = await database;
    await db?.update(
      'timerdata',
      task.toMap(),
      where: "id = ?",
      whereArgs: [task.id],
      conflictAlgorithm: ConflictAlgorithm.replace,
    );
  }

  //update database by title
  Future<void> updateDatabaseByTitle(Task task) async {
    final db = await database;
    await db?.update(
      'timerdata',
      task.toMap(),
      where: "title = ?",
      whereArgs: [task.title],
      conflictAlgorithm: ConflictAlgorithm.replace,
    );
  }
}

在initDb()中,可以使用await db.execute()来等待数据库表的创建完成,避免在创建表之前使用数据库出现问题。
在insert()方法中,可以使用INSERT OR REPLACE语句来实现插入或更新操作,以避免插入重复数据。
在getAll()方法中,可以使用db!.query(‘timerdata’, orderBy: ‘id DESC’)来按照id倒序获取所有数据,这样可以避免获取数据后再排序的操作。
在updateDatabase()和updateDatabaseByTitle()方法中,可以使用update()方法的conflictAlgorithm参数来实现插入或更新操作,以避免更新重复数据的问题。

说明

initDb说明

onCreate是在第一次打开数据库时调用的回调函数,用于创建数据库表和初始化数据。在Dart的sqflite库中,onCreate回调函数的签名为(Database db, int version),其中db参数是打开的数据库对象,version参数是数据库的版本号。

在onCreate回调函数中,我们可以使用db.execute()方法来执行SQL语句,以创建表和初始化数据。例如,在以下代码中:

Database db = await openDatabase(path, version: 1, onCreate: (Database db, int version) async {
  await db.execute('CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, name TEXT)');
  await db.execute('INSERT INTO users (name) VALUES ("Alice")');
});

我们创建了一个名为users的表,并插入了一条记录。具体来说,我们使用了CREATE TABLE IF NOT EXISTS语句来创建一个users表,该表有两个字段:id和name,其中id是主键,name是文本类型。然后,我们使用INSERT INTO语句向users表中插入一条记录,该记录的name字段为"Alice"``onCreate是在第一次打开数据库时调用的回调函数,用于创建数据库表和初始化数据。在Dart的sqflite库中,onCreate回调函数的签名为(Database db, int version),其中db参数是打开的数据库对象,version参数是数据库的版本号。

conflictAlgorithm说明

conflictAlgorithm是在数据插入或更新时发生冲突(例如违反唯一性约束)时的解决策略。在Dart的sqflite库中,有以下四种冲突解决策略:

  1. ConflictAlgorithm.rollback:回滚事务,放弃所有更改。
  2. ConflictAlgorithm.abort:放弃当前操作,但不回滚事务。
  3. ConflictAlgorithm.fail:放弃当前操作,但是不回滚事务,并抛出异常。
  4. ConflictAlgorithm.replace:替换旧数据,或者插入新数据,以解决冲突。

在代码中,ConflictAlgorithm.replace的作用是在插入或更新数据时,如果发生冲突,则用新数据替换旧数据。这种策略可以保证数据的唯一性,并且不会抛出异常。如果数据不存在,则直接插入新数据,如果数据已经存在,则用新数据替换旧数据。

例如,在上面的代码中,updateDatabase()updateDatabaseByTitle()方法中使用了conflictAlgorithm: ConflictAlgorithm.replace参数,以避免更新或插入重复数据。如果表中已经存在具有相同id或title的数据,则会用新数据替换旧数据,否则直接插入新数据。

之前写的界面,数据用数据库保存后的效果如下图:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/571200.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【CSDN快速获得铁粉小经验】厉昱辰的经验分享

如何快速的涨粉呢&#xff1f;今天将带领大家一起涨粉喽&#x1f970;&#x1f970;&#x1f973;&#x1f973; 一、最低阅读量过滤 官方算法进行最低阅读量过滤&#xff0c;阅读量太低的直接不参与热榜计算&#xff0c;刚创建的文章应该在其他渠道有一些冷启动的过程。但是阅…

c++ 11标准模板(STL) std::map(四)

定义于头文件<map> template< class Key, class T, class Compare std::less<Key>, class Allocator std::allocator<std::pair<const Key, T> > > class map;(1)namespace pmr { template <class Key, class T, clas…

150套开发板免费送!还有5G手机拿?米尔RZ/G2L开发板创意秀

人间最美五月天 不负韶华不负卿 米尔又来送板子了 不是3套&#xff0c;也不是4套 150套米尔RZ/G2L开发板 送&#xff01;免费&#xff01;板卡不回收&#xff01; 这是什么样的有奖活动&#xff1f; 米尔RZ/G2L开发板创意秀 为感谢广大客户一直以来的支持&#xff0c;推动…

15 个非常流行的VsCode插件,让你的编码效率倍增!

VS Code已经成为了最受欢迎的代码编辑器之一。 它的简洁性、易用性和可扩展性使得它成为了许多开发者的首选。 而在VS Code中&#xff0c;插件是其最大的卖点之一。 通过安装插件&#xff0c;你可以将VS Code打造成一个功能强大的开发环境&#xff0c;从而提高你的编码效率。…

【2023A题】电采暖负荷参与电力系统功率调节的技术经济分析(思路、代码)

目录 &#x1f4a5;1 概述 &#x1f4da;2 Matlab代码实现 &#x1f389;3 参考文献 &#x1f308;4 运行结果 &#x1f4a5;1 概述 建设以新能源为主体的新型电力系统是应对全球气候变化挑战的重要举措。高比例新能源接入导致电力系统调节能力稀缺&#xff0c;亟需开发新的调…

Node版本管理器nvm的安装与使用

前言&#xff1a; 多项目新旧项目管理的时候&#xff0c;往往与依赖不同的node版本&#xff0c;不同的版本对其他依赖的安装有一定的影响&#xff0c;因此我们需要对node的版本进行方便快捷管理和切换&#xff0c;如果直接卸载重装对应版本&#xff0c;切换项目再次卸载重装明显…

word打印为pdf去掉批注和修订记录

对于这个问题某乎上充斥着垃圾回答&#xff0c;大多引流到自家开发的pdf产品上。其实背后的方法都是一样的&#xff0c;就是关掉批注&#xff0c;用word自带的功能就能解决&#xff0c;凡是word编辑软件都有类似功能 直接用word打印为pdf后的效果 下图为打印出来的pdf文件&…

杜绝开源依赖风险,许可证扫描让高效合规「两不误」

目录 开源许可证及其常见类型 开源许可证扫描是软件研发过程中&#xff0c;不可或缺的工具 极狐GitLab 开源许可证扫描的优势与应用 Step 1&#xff1a;启用及设置许可证策略 Step 2&#xff1a;自动创建策略文件存放项目 Step 3&#xff1a;查看许可证合规情况 Step 4&…

<Linux开发>驱动开发 -之-gpio子系统

&#xff1c;Linux开发&#xff1e;驱动开发 -之-gpio子系统 交叉编译环境搭建&#xff1a; &#xff1c;Linux开发&#xff1e; linux开发工具-之-交叉编译环境搭建 uboot移植可参考以下&#xff1a; &#xff1c;Linux开发&#xff1e; -之-系统移植 uboot移植过程详细记录&…

vue实现倒计时功能

vue实现倒计时功能 首先我们需要一个 Vue. js的函数&#xff0c;这个函数用于实现倒计时&#xff0c;这里我们采用 vue. js的 import来实现&#xff0c;这是 vue. js的一个特殊功能&#xff0c;将函数调用的参数以列表的形式加入到函数中&#xff0c;当在函数执行完后返回结果。…

Java基础--->IO流(2)【常见IO模型】

文章目录 计算机角度IO操作系统IO常见的IO模型Java 中 3 种常见 IO 模型BIO&#xff08;BlockingI/O&#xff09;【同步阻塞IO】NIO&#xff08;Non-blocking/New I/O&#xff09;【非阻塞IO】IO多路复用AIO&#xff08;Asynchronous I/O&#xff09;【异步IO】 计算机角度IO 根…

进攻中型SUV,蔚来/小鹏的智能化「满配」能否撬动需求

251.29万辆&#xff0c;这是2022年中国市场&#xff08;不含进出口&#xff09;乘用车中型SUV交出的答卷&#xff0c;交付量仅次于紧凑型SUV&#xff0c;排名细分市场第二。在这份成绩单中&#xff0c;有几个数字特别醒目。 1、31.64万辆&#xff0c;这是排名这个细分市场交付量…

chatgpt赋能python:Python交易股票:掌握交易技巧,开启财富增长之路

Python 交易股票&#xff1a;掌握交易技巧&#xff0c;开启财富增长之路 股票市场一直以来都是吸引人们收益的地方&#xff0c;不断变化的市场行情也让每一位投资者都不得不面对各种风险。然而&#xff0c;如果您懂得运用好 Python 来交易股票&#xff0c;就能够更好地理解市场…

【软考-中级】系统集成项目管理工程师 【14 采购管理】

持续更新。。。。。。。。。。。。。。。 【第十四章】采购管理 2 分 14.1采购管理的相关概念和主要过程14.1.1 概念和术语14.1.2 采购管理的主要过程 14.2编制采购管理计划14.2.1编制采购计划的输入、输出14.2.2用于编制采购计划过程的技术和方法14.2.3工作说明书 历年真题202…

小程序外包开发上线流程

小程序有非常多的优势&#xff0c;无需下载安装、使用方便、开发成本低、覆盖广泛、轻量级、方便推广&#xff0c;这些特点使得小程序非常适合场景不太复杂的场合&#xff0c;这些年出现了大量的小程序。今天和大家分享一下小程序的一些特点和上线流程&#xff0c;希望对大家有…

C#,码海拾贝(21)——“全选主元高斯消去法“求解“线性方程组“的C#源代码,《C#数值计算算法编程》源代码升级改进版

using System; namespace Zhou.CSharp.Algorithm { /// <summary> /// 求解线性方程组的类 LEquations /// 原作 周长发 /// 改编 深度混淆 /// </summary> public static class LEquations { /// <summary> /…

mysql倒库操作遇到的问题

背景&#xff1a;本地windows 10安装了mysql数据库后&#xff0c;需要把远程库的表结构和数据全部导入进来。 操作&#xff1a;导出数据库&#xff0c;导入数据库。 第一步&#xff1a;导出数据库 使用dump命令即可。 登陆mysql数据库 mysql -hhost --default-character-s…

springboot整合ueditor有源码

在项目用到ueditor插件来编辑信息&#xff0c;初次接触&#xff0c;遇到各种问题&#xff0c;到目前为止&#xff0c;也只是基本实现了功能&#xff0c;简单记录一下过程&#xff0c;希望对初次使用ueditor的朋友们有所帮助。 ueditor就不介绍了&#xff0c;或对ueditor还不了…

尝试 python flink

引入pyflink库 启动anaconda的终端窗口 执行命令 pip install apache-flink1.13.2 等待安装flink相关库

< ElementUi组件库: el-progress 进度条Bug及样式调整 >

ElementUi组件库&#xff1a; el-progress 进度条Bug及样式调整 &#x1f449; 前言&#x1f449; 一、实现原理> 修改 el-progress 进度条样式 及 渐变进度条样式 &#x1f449; 二、案例代码&#xff08;前言效果图案例&#xff09;> HTML代码> CSS代码 &#x1f44…