flutter开发实战-本地SQLite数据存储

news2025/1/20 5:45:57

flutter开发实战-本地SQLite数据库存储

正在编写一个需要持久化且查询大量本地设备数据的 app,可考虑采用数据库。相比于其他本地持久化方案来说,数据库能够提供更为迅速的插入、更新、查询功能。这里需要用到sqflite package 来使用 SQLite 数据库

预览图
在这里插入图片描述

一、引入sqflite

在工程的pubspec.yaml中引入插件

  # sqflite
  sqflite: ^2.2.8+4
    

二、使用sqflite

使用 sqflite 实现插入,读取,更新,删除数据。

  • 打开数据库
  Future<void> openDB(BuildContext context) async {
    // Open the database and store the reference.
    database = await openDatabase(
      // Set the path to the database. Note: Using the `join` function from the
      // `path` package is best practice to ensure the path is correctly
      // constructed for each platform.
      join(await getDatabasesPath(), 'doggie_database.db'),
      // When the database is first created, create a table to store dogs.
      onCreate: (db, version) {
        // Run the CREATE TABLE statement on the database.
        return db.execute(
          'CREATE TABLE dogs(id INTEGER PRIMARY KEY, name TEXT, age INTEGER)',
        );
      },
      version: 1,
    );
  }
    
  • 插入一条记录
Future<void> insertDB(BuildContext context) async {
    dogId++;

    // Create a Dog and add it to the dogs table
    var fido = Dog(
      id: dogId,
      name: 'Fido',
      age: 35,
    );

    // Get a reference to the database.
    final db = await database;

    // Insert the Dog into the correct table. You might also specify the
    // `conflictAlgorithm` to use in case the same dog is inserted twice.
    //
    // In this case, replace any previous data.
    await db?.insert(
      'dogs',
      fido.toMap(),
      conflictAlgorithm: ConflictAlgorithm.replace,
    );
  }
    
  • 更新一条记录
  Future<void> updateDog(Dog dog) async {
    // Get a reference to the database.
    final db = await database;

    // Update the given Dog.
    await db?.update(
      'dogs',
      dog.toMap(),
      // Ensure that the Dog has a matching id.
      where: 'id = ?',
      // Pass the Dog's id as a whereArg to prevent SQL injection.
      whereArgs: [dog.id],
    );
  }
    
  • 删除一条记录
  Future<void> deleteDog(int id) async {
    // Get a reference to the database.
    final db = await database;

    // Remove the Dog from the database.
    await db?.delete(
      'dogs',
      // Use a `where` clause to delete a specific dog.
      where: 'id = ?',
      // Pass the Dog's id as a whereArg to prevent SQL injection.
      whereArgs: [id],
    );
  }
    
  • 获取存储记录
  // A method that retrieves all the dogs from the dogs table.
  Future<List<Dog>> dogs() async {
    // Get a reference to the database.
    final db = await database;

    // Query the table for all the dogs.
    final List<Map<String, Object?>>? dogMaps = await db?.query('dogs');

    if (dogMaps != null && dogMaps.isNotEmpty) {
      // Convert the list of each dog's fields into a list of `Dog` objects.
      List<Dog> dogs = [];
      for(var dogMap in dogMaps) {
        // Dog dog = Dog(id: dogMap['id']??0, name: name, age: age)
        var id = dogMap['id'] as int;
        var name = dogMap['name'] as String;
        var age = dogMap['age'] as int;

        Dog dog = Dog(id: id, name: name, age: age);
        dogs.add(dog);
      }
      return dogs;
    }

    return [];
  }
    

完整代码如下

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

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

class SqliteDemoPage extends StatefulWidget {
  const SqliteDemoPage({super.key});

  @override
  State<SqliteDemoPage> createState() => _SqliteDemoPageState();
}

class _SqliteDemoPageState extends State<SqliteDemoPage> {
  Database? database;

  int dogId = 0;

  Future<void> openDB(BuildContext context) async {
    // Open the database and store the reference.
    database = await openDatabase(
      // Set the path to the database. Note: Using the `join` function from the
      // `path` package is best practice to ensure the path is correctly
      // constructed for each platform.
      join(await getDatabasesPath(), 'doggie_database.db'),
      // When the database is first created, create a table to store dogs.
      onCreate: (db, version) {
        // Run the CREATE TABLE statement on the database.
        return db.execute(
          'CREATE TABLE dogs(id INTEGER PRIMARY KEY, name TEXT, age INTEGER)',
        );
      },
      version: 1,
    );
  }

  // A method that retrieves all the dogs from the dogs table.
  Future<List<Dog>> dogs() async {
    // Get a reference to the database.
    final db = await database;

    // Query the table for all the dogs.
    final List<Map<String, Object?>>? dogMaps = await db?.query('dogs');

    if (dogMaps != null && dogMaps.isNotEmpty) {
      // Convert the list of each dog's fields into a list of `Dog` objects.
      List<Dog> dogs = [];
      for(var dogMap in dogMaps) {
        // Dog dog = Dog(id: dogMap['id']??0, name: name, age: age)
        var id = dogMap['id'] as int;
        var name = dogMap['name'] as String;
        var age = dogMap['age'] as int;

        Dog dog = Dog(id: id, name: name, age: age);
        dogs.add(dog);
      }
      return dogs;
    }

    return [];
  }

  Future<void> updateDog(Dog dog) async {
    // Get a reference to the database.
    final db = await database;

    // Update the given Dog.
    await db?.update(
      'dogs',
      dog.toMap(),
      // Ensure that the Dog has a matching id.
      where: 'id = ?',
      // Pass the Dog's id as a whereArg to prevent SQL injection.
      whereArgs: [dog.id],
    );
  }

  Future<void> deleteDog(int id) async {
    // Get a reference to the database.
    final db = await database;

    // Remove the Dog from the database.
    await db?.delete(
      'dogs',
      // Use a `where` clause to delete a specific dog.
      where: 'id = ?',
      // Pass the Dog's id as a whereArg to prevent SQL injection.
      whereArgs: [id],
    );
  }


  Future<void> insertDB(BuildContext context) async {
    dogId++;

    // Create a Dog and add it to the dogs table
    var fido = Dog(
      id: dogId,
      name: 'Fido',
      age: 35,
    );

    // Get a reference to the database.
    final db = await database;

    // Insert the Dog into the correct table. You might also specify the
    // `conflictAlgorithm` to use in case the same dog is inserted twice.
    //
    // In this case, replace any previous data.
    await db?.insert(
      'dogs',
      fido.toMap(),
      conflictAlgorithm: ConflictAlgorithm.replace,
    );
  }

  Future<void> getListFromDB(BuildContext context) async {
    List<Dog> list = await dogs();
    for(var dog in list) {
      print("dog info:${dog.toString()}");
    }
  }

  void updateDB(BuildContext context) {
    var dog = Dog(
      id: dogId,
      name: 'AFarah',
      age: 11,
    );
    updateDog(dog);
  }

  Future<void> deleteDB(BuildContext context) async {
    await deleteDog(dogId);
    dogId--;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('SqliteDemo'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            const SizedBox(
              height: 20,
            ),
            TextButton(
              onPressed: () {
                openDB(context);
              },
              child: Container(
                height: 36,
                width: 200,
                color: Colors.lightGreen,
                alignment: Alignment.center,
                child: const Text(
                  'openDatabase',
                  style: TextStyle(fontSize: 12, color: Colors.white),
                ),
              ),
            ),
            const SizedBox(
              height: 20,
            ),
            TextButton(
              onPressed: () {
                insertDB(context);
              },
              child: Container(
                height: 36,
                width: 200,
                color: Colors.lightGreen,
                alignment: Alignment.center,
                child: const Text(
                  '插入一条dog记录',
                  style: TextStyle(fontSize: 12, color: Colors.white),
                ),
              ),
            ),
            const SizedBox(
              height: 20,
            ),
            TextButton(
              onPressed: () {
                getListFromDB(context);
              },
              child: Container(
                height: 36,
                width: 200,
                color: Colors.lightGreen,
                alignment: Alignment.center,
                child: const Text(
                  '获取记录列表',
                  style: TextStyle(fontSize: 12, color: Colors.white),
                ),
              ),
            ),
            const SizedBox(
              height: 20,
            ),
            TextButton(
              onPressed: () {
                updateDB(context);
              },
              child: Container(
                height: 36,
                width: 200,
                color: Colors.lightGreen,
                alignment: Alignment.center,
                child: const Text(
                  '更新一条记录',
                  style: TextStyle(fontSize: 12, color: Colors.white),
                ),
              ),
            ),
            const SizedBox(
              height: 20,
            ),
            TextButton(
              onPressed: () {
                deleteDB(context);
              },
              child: Container(
                height: 36,
                width: 200,
                color: Colors.lightGreen,
                alignment: Alignment.center,
                child: const Text(
                  '删除一条记录',
                  style: TextStyle(fontSize: 12, color: Colors.white),
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

class Dog {
  final int id;
  final String name;
  final int age;

  const Dog({
    required this.id,
    required this.name,
    required this.age,
  });

  // Convert a Dog into a Map. The keys must correspond to the names of the
  // columns in the database.
  Map<String, Object?> toMap() {
    return {
      'id': id,
      'name': name,
      'age': age,
    };
  }

  // Implement toString to make it easier to see information about
  // each dog when using the print statement.
  @override
  String toString() {
    return 'Dog{id: $id, name: $name, age: $age}';
  }
}

    

三、小结

flutter开发实战-本地SQLite数据库存储

学习记录,每天不停进步。

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

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

相关文章

如何快速生成接口文档(swagger和knife4j两种方式及其使用)

如何快速生成接口文档&#xff08;swagger和knife4j两种方式&#xff09; 1、什么是接口文档&#xff1f; 在项目开发中&#xff0c;web项目的前后端分离开发&#xff0c;APP开发&#xff0c;需要由前后端工程师共同定义接口&#xff0c;编写接口文档&#xff0c;之后大家都根…

使用PyQt5设计订单查询界面—了解界面布局2

想要实现的界面效果 增加Tab Widge的页签 在MainWindow窗口中选中水平布局&#xff0c;将一个Label控件和一个默认自带两个页签的Tab Widget控件放到水平布局中&#xff0c;Tab Widget控件右键选择“插入页”再选择“在当前页之后”增加页签。 为每一个Tab页签界面都选择“栅格…

【小积累】@Qualifier注解

今天在看rabbitMQ的时候需要绑定交换机和队列&#xff0c;交换机和队列都已经注入到spring容器中&#xff0c;写了一个配置类&#xff0c;使用了bean注解注入的。所以这时候绑定的时候需要使用容器中的交换机和队列&#xff0c;必须要使用Qualifier去确定是容器中的哪个bean对象…

240W 宽电压输入 AC/DC 导轨式开关电源——TPR/SDR-240-XS 系列

TPR/SDR-240-XS 导轨式开关电源&#xff0c;额定输出功率为240W&#xff0c;产品输入范围&#xff1a;85-264VAC。提供24V、48V输出&#xff0c;具有短路保护&#xff0c;过载保护等功能&#xff0c;并具备高效率&#xff0c;高可靠性、高寿命、更安全、更稳定等特点&#xff0…

Uncaught InternalError: too much recursion

今天在敲代码的时候偶然间发现项目因为一次操作导致浏览器变得非常卡&#xff0c;而且控制台还报错了 Uncaught InternalError: too much recursior 页面截图如下 &#xff1a; 突如起来的报错和页面异常卡顿给我整不会了ovo&#xff0c;点开报错的地方&#xff0c;直接跳转到对…

FullCalendar日历组件集成实战(3)

背景 有一些应用系统或应用功能&#xff0c;如日程管理、任务管理需要使用到日历组件。虽然Element Plus也提供了日历组件&#xff0c;但功能比较简单&#xff0c;用来做数据展现勉强可用。但如果需要进行复杂的数据展示&#xff0c;以及互动操作如通过点击添加事件&#xff0…

【Linux线程(二)】线程互斥和同步

前言&#xff1a; 在上一篇博客中&#xff0c;我们讲解了什么是线程以及如何对线程进行控制&#xff0c;那么了解了这些&#xff0c;我们就可以在程序中创建多线程了&#xff0c;可是多线程往往会带有许多问题&#xff0c;比如竞态条件、死锁、数据竞争、内存泄漏等问题&#…

【Unity】 HTFramework框架(四十八)使用Location设置Transform位置、旋转、缩放

更新日期&#xff1a;2024年5月14日。 Github源码&#xff1a;[点我获取源码] Gitee源码&#xff1a;[点我获取源码] 索引 Location定义Location复制Location变量的值复制Transform组件的Location值粘贴Location变量的值粘贴Location值到Transform组件在代码中使用Location Loc…

GPT-4o omni全能 openAI新flagship旗舰模型,可以通过音频、视觉、文本推理。自然人机交互,听懂背景噪音、笑声、歌声或表达情感,也能输出。

新旗舰模型GPT-4o GPT-4o 是openAI新flagship旗舰模型&#xff0c;可以通过音频、视觉、文本推理reason&#xff0c;也能组合输出text, audio, and image。 接受文本、音频和图像的任意组合作为输入&#xff0c;并生成文本、音频和图像输出的任意组合。 速度快 2 倍&#xff…

华火5.0台嵌式喷火电燃单灶,更懂未来生活需求

在厨电技术不断革新的今天&#xff0c;第五代华火电燃灶以其独特的技术升级和卓越性能&#xff0c;成功吸引了市场的广泛关注。作为华火品牌的最新力作&#xff0c;第五代电燃灶不仅继承了前代产品的优点&#xff0c;更在多个方面进行了显著的升级和创新。下面&#xff0c;我们…

PXI/PXIe规格 A429/717 航电总线适配卡

A429是一款标准的PXI/PXIe1规格的多协议总线适配卡。该产品最多支持36个A429通道&#xff0c;或32个A429通道加4个A717通道&#xff0c;每个A429和A717通道可由软件配置成接收或发送&#xff0c;可满足A429总线和A717总线的通讯、测试和数据分析等应用需求。 该产品的每个A429通…

Simulink|虚拟同步发电机(VSG)惯量阻尼自适应控制仿真模型

主要内容 该模型为simulink仿真模型&#xff0c;主要实现的内容如下&#xff1a; 随着风力发电、光伏发电等新能源发电渗透率增加&#xff0c;电力系统的等效惯量和等效阻尼逐渐减小&#xff0c;其稳定性问题变得越来越严峻。虚拟同步发电机&#xff08;VSG&#xff09;技…

Django项目之电商购物商城 -- 修改/删除收货地址/设置默认地址

Django项目之电商购物商城 – 修改/删除收货地址/设置默认地址 修改和删除收货地址依旧实在user应用下进行 , 其思路和新增收货地址非常相似 依旧是更具前端的数据来写 在这里修改和删除地址的URL是相同的 , 所以我们只要设置一个模型类就可以实现这两个功能 一 . 修改地址…

Go 多模块工作区处理一个go项目下有多个module(即多个go.mod)的情况

背景 在现在微服务盛行的年代&#xff0c;一个人会维护多个代码仓库&#xff0c;很多的时候是多个仓库进行同时开发&#xff0c;也就是在当前项目下有多个目录&#xff0c;每个目录对应一个微服务&#xff0c;每个微服务都有一个go.mod文件。那么我在其中一个目录下要怎么导入…

4.Jmeter阶梯加压Stepping Thread Group

1. 先去Jmeter下载地址下载PluginsManager&#xff0c;放置在Jmeter的lib/ext 目录下 &#xff0c;重启Jmeter 2. 在插件管理器查找并安装jpgc - Standard Set,重启Jmeter 3.右键测试计划->添加->Threads(Users)->jpgc - Stepping Thread Group 然后设置阶梯加压参数…

java中不可变对象使用避坑

总结&#xff1a; 1&#xff0c;不要大量使用不可变对象和不可边对象提供的方法&#xff08;每次调用不可变对象的修改方法会创建出新的对象出来&#xff0c;导致频繁的YGC&#xff09; 2&#xff0c;计算密集型任务不要使用包装类&#xff08;包装类体积大&#xff0c;数据密度…

数据中心逆变电源的功率容量计算方法

随着信息技术的快速发展&#xff0c;数据中心在现代社会中的地位日益凸显&#xff0c;各种企业和机构对数据中心的依赖程度也越来越高。而电源作为数据中心的核心基础设施&#xff0c;其可靠性和高效性直接影响着数据中心的稳定运行。因此&#xff0c;如何设计一款性能优越、可…

OpenAI 今日(北京时间 5 月 14 日凌晨两点)将发布的大更新,不是 GPT-5,也不是搜索引擎

&#x1f989; AI新闻 &#x1f680; OpenAI 今日&#xff08;5月13日&#xff09;将发布的大更新&#xff0c;不是 GPT-5&#xff0c;也不是搜索引擎 摘要&#xff1a;OpenAI 预计即将推出一款新的 AI 语音助手&#xff0c;该助手不仅可以进行语音和文字交流&#xff0c;还能…

【JavaScript】---- 使用 Tween 实现转盘抽奖

1. 实现效果 2. 需求分析 它和正常的转盘抽奖不一样&#xff0c;一般实现都是指针形式的&#xff0c;转盘转动&#xff0c;最后指针停留在奖品的随机位置&#xff1b;通过上边图发现奖品必须刚好停留在奖品的位置&#xff0c;因为不是指针&#xff0c;所以不能最后落到随机位置…

伦敦银晚盘预测方法:以经济数据为基础

晚盘是指北京时间晚上8点到凌晨的这个时段&#xff0c;覆盖了部分欧盘和大部分的美盘。一般来说&#xff0c;这个时段有欧美方面&#xff08;主要是美国&#xff09;的经济数据公布&#xff0c;其中一些重要的数据&#xff0c;如通胀数据、美联储公布利率决议等等&#xff0c;会…