Flutter中数据库的使用教程详解
作者:老李code 发布时间:2023-12-09 11:16:28
在Flutter开发过程中,我门有时候需要对一些数据进行本地的持久化存储,使用sp文件形式虽然也能解决问题,但是有时数据量较大的时候,显然我们文件形式就不太合适了,这时候我们就需要使用数据库进行存储,我们知道在原生中有系统提供的轻量级sqlite
数据库,在Flutter强大的生态环境中,也有这样一个数据库插件sqflite: ^2.0.2
可以同时在Androud、iOS
中进行数据库操作。
1、 创建数据库:这里我以存储我的搜索历史记录为例。
首先导入:
import 'package:sqflite/sqflite.dart';
这里我创建了一个数据库帮助类,为了以后数据库更新、升级等作准备:
代码实现:主要是对Database这个类的获取进行了封装。
/// 数据库帮助类
class DbHelper {
final String path = "laoli.db"; // 数据库名称 一般不变
//数据库中的表名字 这里是我存错历史搜索记录的表
static final searchTab = "SearchHistory";
//私有构造
DbHelper._();
static DbHelper? _instance;
static DbHelper get instance => _getInstance();
factory DbHelper() {
return instance;
}
static DbHelper _getInstance() {
if (_instance == null) {
_instance = DbHelper._();
}
return _instance ?? DbHelper._();
}
/// 数据库默认存储的路径
/// SQLite 数据库是文件系统中由路径标识的文件。如果是relative,
/// 这个路径是相对于 获取的路径getDatabasesPath(),
/// Android默认的数据库目录,
/// iOS/MacOS的documents目录。
Future<Database>? _db;
Future<Database>? getDb() {
_db ??= _initDb();
return _db;
}
// Guaranteed to be called only once.保证只调用一次
Future<Database> _initDb() async {
// 这里是我们真正创建数据库的地方 vserion代表数据库的版本,如果版本改变
//,则db会调用onUpgrade方法进行更新操作
final db =
await openDatabase(this.path, version: 1, onCreate: (db, version) {
// 数据库创建完成
// 创建表 一个自增id 一个text
db.execute("create table $searchTab (id integer primary key autoincrement, name text not null)");
}, onUpgrade: (db, oldV, newV) {
// 升级数据库调用
/// db 数据库
/// oldV 旧版本号
// newV 新版本号
// 升级完成就不会在调用这个方法了
});
return db;
}
// 关闭数据库
close() async {
await _db?.then((value) => value.close());
}
}
在java
后台开发过程中,数据库肯定都会分层设计,这样的好处可以在使用的过程中极大的提高代码的健壮性以及降低后期的维护成本,在移动前端虽然我们用数据库的地方跟后台相比少之又少,但是我还是建议也对数据库进行分层处理操作,虽然不分层也能实现,但是这样也可以降低我们的对于代码的维护成本以及良好的编程习惯。废话不多说,接下来我们需要创建处理数据的dao
层。
这里sqflite
封装了一些常用的sql
语法,比如增删改查,我们就不需要自己去写sql语法了,这里我简答封装了下增删改查的方法。
具体代码:
/// 数据操作类
class DbSearchHistoryDao {
/// 增
static insert(String text) {
// 去重
queryAll().then((value) {
bool isAdd = true;
for (var data in value) {
if (data.name == text) {
isAdd = false;
break;
}
}
if (isAdd) {
DbHelper.instance.getDb()?.then((value) => value.insert(
DbHelper.searchTab,
DbSearchHotBean(name: text).toJson(),
));
}
});
}
/// 删 全部
static deleteAll() {
DbHelper.instance.getDb()?.then((value) => value.delete(
DbHelper.searchTab,
));
}
/// 更新数据 通过id更新表内具体行的数据
static update(DbSearchHotBean dbSearchHotBean) {
DbHelper.instance.getDb()?.then((value) => value.update(
DbHelper.searchTab,
dbSearchHotBean.toJson(),//具体更新的数据
where: "id = ?"//通过id查找需要更新的数据
,whereArgs: [dbSearchHotBean.id]
));
}
/// 通过name查具体的实体类
static Future<DbSearchHotBean?> getBean(String name) async {
var db = await DbHelper.instance.getDb();
var maps = await db?.query(DbHelper.searchTab,
columns: ['id','name'],// 获取实体类的哪些字段 默认全部
where: 'name = ?',//通过实体类中的name字段
whereArgs: [name]);//具体name的值 限定数据
if(maps!=null && maps.length > 0) {
return DbSearchHotBean.fromJson(maps.first);
}
return null;
}
/// 查 全部all
static Future<List<DbSearchHotBean>> queryAll() async {
List<DbSearchHotBean> list = [];
await DbHelper.instance
.getDb()
?.then((db) => db.query(DbHelper.searchTab).then((value) {
for (var data in value) {
list.add(DbSearchHotBean.fromJson(data));
}
}));
return list;
}
}
实体类:虽然只有一个字段,但是创建实体类方便以后扩展。
class DbSearchHotBean {
int? id;
String? name; // 搜索词
DbSearchHotBean({this.id,required this.name});
DbSearchHotBean.fromJson(Map<String, dynamic> json) {
id = json['id'];
name = json['name'];
}
Map<String, String?> toJson() {
var map = <String, String?>{};
map['id'] = id?.toString() ;
map['name'] = name ?? "";
return map;
}
}
具体用法就非常简单了:
增:DbSearchHistoryDao.insert(”搜索词“);
删全部:DbSearchHistoryDao.deleteAll();
改:例如将水改为火, 找到水的实体通过自增id修改name
DbSearchHistoryDao.getBean("水").then((value){
if(value!=null){
DbSearchHistoryDao.update(DbSearchHotBean(id: value.id,name: "火"));
}
});
查全部:await DbSearchHistoryDao.queryAll();
到这里数据库的基本用法就介绍完了,当然部分操作比如删指定数据,批量修改、批量删除等操作可以用 到批处理操作,这里就不过多介绍了,有需要的可以查看作者文档。链接
batch = db.batch();
batch.insert('Test', {'name': 'item'});
batch.update('Test', {'name': 'new_item'}, where: 'name = ?', whereArgs: ['item']);
batch.delete('Test', where: 'name = ?', whereArgs: ['item']);
results = await batch.commit();
总结
数据库操作总体上没什么难度,但是当我们数据量比较多的时候,数据表结构的设计就有一定的技术含量了,还有就是我们对于一些sql语句的掌握,因为此插件帮我们封装了常用的功能,如果有比较特殊的需求,还是需要我们掌握一定的sql语法才行,这里就简单的介绍一些常用的方法,在移动前端估计也基本够用了~
来源:https://juejin.cn/post/7084536128077824037
猜你喜欢
- 本文实例讲述了C#调用Oracle存储过程的方法。分享给大家供大家参考。具体实现方法如下:Oracle数据库代码如下:create or r
- 本文我们将要讨论Java面试中的各种不同类型的面试题,它们可以让雇主测试应聘者的Java和通用的面向对象编程的能力。下面的章节分为上下两篇,
- 注意:不同的JDK版本的扩容机制可能有差异实验环境:JDK1.8扩容机制:当向ArrayList中添加元素的时候,ArrayList如果要满
- CollectionUtils.isNotEmpty()不存在问题org.apache.commons.collections.Collec
- 这周在做公司的一个C#项目中,要写一个webservice提供一个下载方法,之前公司有过,但是要整改,于是这种鸟屎摊子又交给了我,其中一个密
- 一、SpringMVC使用1.工程创建创建maven工程。添加java、resources目录。引入Spring-webmvc 依赖。<
- 上篇文章给大家介绍了,喜欢的朋友点击查看下。SpringBoot 开发提速神器 Lombok+MybatisPlus+SwaggerUILo
- Java继承方法重写是Java语言多态的特性,必须满足以下条件在子类中,方法名称与父类方法名称完全相同方法的参数个数和类型完全相同,返回类型
- 一,简介Feign使得 Java HTTP 客户端编写更方便。Feign 灵感来源于Retrofit、JAXRS-2.0和WebSocket
- 1,实现方法一:通过给当前界面布局文件的父layout设置点击事件(相当于给整个Activity设置点击事件),在事件里进行键盘隐藏<
- jmap命令可以打印java进程的JVM堆信息,今天在某台机器上运行该命令查看 19560进程的堆信息jmap -heap 19560出现以
- 在Java项目开发中,Maven是非常重要的构建工具之一,它可以帮助我们管理项目的依赖、构建和发布。本文将通过以下两个方面来介绍Maven打
- 本文实例为大家分享了C#类的多态性,供大家参考,具体内容如下第一种:编译时的多态性,直接这样说不知道说啥?程序执行过程主要分为三步:编译,链
- 本文实例演示了Java多线程死锁。分享给大家供大家参考,具体如下:package com.damlab.fz;public class De
- 本文实例为大家分享了基于servlet实现统计网页访问次数的具体代码,供大家参考,具体内容如下一、基础知识(1)ServletContext
- 一、前置说明本节大纲使用lombok插件的好处如何安装lombok插件使用lombok提高开发效率二、使用lombok插件的好处我们在jav
- 一、序言(一)背景内容软件应用技术架构中DAO层最常见的选型组件为MyBatis,熟悉MyBatis的朋友都清楚,曾几何时MyBatis是多
- 动态内存管理为什么存在动态内存分配我们到现在为止掌握的是什么样的内存开辟方式呢//创建一个变量int val = 20; &n
- 短网址(Short URL) ,顾名思义就是看起来很短的网址。自从twitter推出短网址服务以后,各大互联网公司都推出了自己的短网址服务。
- 本文实例讲述了Android获取当前已连接的wifi信号强度的方法,是Android程序开发中非常常见的重要技巧。分享给大家供大家参考之用。