正文:
在Flutter
中,我们可以使用 Sqlite
作为本地数据库来存储和管理数据。为了方便使用,我们可以进行二次封装,创建一个基类来处理常见的数据库操作。
安装 Sqlite
插件
首先我们需要安装 Sqlite
插件
// https
://www
.huizhanii
.com
sqflite
: ^2.0.2
创建基类,用来实例化数据库
return
_database
!;
}
}
基类已经准备好初始化数据库的工作。当子类继承基类时,会触发数据库初始化事件。在数据库初始化完成后,基类还需要执行以下操作:
1. 创建表格:触发子类的创建表格事件。但是,如果表格已经存在,重复创建会导致错误,因此该函数只能触发一次。
2. 数据库升级或降级:触发子类的数据库升级或降级事件,并且也只能触发一次。
添加建表功能
为了触发子类的创建表格事件,并且只触发一次,我们可以在基类中定义一个创建表格的函数,并要求子类必须重写该函数。在重写函数中,判断表格是否存在,如果不存在则创建。
sql
ite_master
var
res
= await
_database
!.rawQuery
(
"SELECT
* FROM
sqlite_master
WHERE
TYPE
= 'table
' AND
NAME
= '$tableName
'",
);
return
res
.isNotEmpty
;
}
}
数据库升级或降级
在基类中我们实现了建表的功能, 同理数据库升级或降级也可以这样写
简易版增删改查
好了现在我们有了建表的功能, 但是我们还需要对表进行增删改查, 所以接下来我们封装一个简易的增删改查功能
开始实验
新建一个 user_info
实体类, 继承 EntityPlus
// https
://www
.huizhanii
.com
class
UserInfoEntity
extends
EntityPlus
{
@override
String
tableName
= "user_info
";
//建表函数,当数据库中没有这个表时,基类会触发这个函数
@override
onCreate
(db
, version
) async
{
print
("创建 $tableName
数据表");
await
db
.execute
("""
CREATE
TABLE
$tableName
(
id
integer
primary
key
autoincrement
,
name
TEXT
,
sex
INTEGER
,
phone
TEXT
)
""");
}
///当数据库升级时,基类会触发的函数
@override
onUpgrade
(db
, oldVersion
, newVersion
) {}
///当数据库降级,基类会触发的函数
@override
onDowngrade
(db
, oldVersion
, newVersion
) {}
}
页面中操作 user_info
表
cat
ch
(err
) {
//注意由于打开数据库属于异步操作, 虽然 UserInfoEntity
已经实例化了, 但是数据库的初始化并没有完成
print
("报错了: $err
");
}
}
@override
Widget
build
(BuildContext
context
) {
return
const
Scaffold
();
}
}
在这种情况下,我们需要考虑一些问题:
1. 当我们直接实例化时,打开数据库是一个异步操作,数据库可能还没有初始化完成,因此操作数据库肯定会发生异常。
2. 每次操作数据库都要实例化一次,这可能会浪费内存。
为了解决以上问题,我们可以将 UserInfoEntity
改成单例模式。
// https
://www
.huizhanii
.com
class
UserInfoEntity
extends
EntityPlus
{
static
UserInfoEntity
? _ins
;
UserInfoEntity
._
();
static
UserInfoEntity
instan
() {
if
(_ins
== null
) {
print
("实例化");
}
return
_ins
??= UserInfoEntity
._
();
}
@override
String
tableName
= "user_info
";
//建表函数,当数据库中没有这个表时,基类会触发这个函数
@override
onCreate
(db
, version
) async
{
print
("创建 $tableName
数据表");
await
db
.execute
("""
CREATE
TABLE
$tableName
(
id
integer
primary
key
autoincrement
,
name
TEXT
,
sex
INTEGER
,
phone
TEXT
)
""");
}
///当数据库升级时,基类会触发的函数
@override
onUpgrade
(db
, oldVersion
, newVersion
) {}
///当数据库降级,基类会触发的函数
@override
onDowngrade
(db
, oldVersion
, newVersion
) {}
}
然后再新建一个类,用来存放所有实体类, 将所有实体类先进行实例化
由于第一次安装应用,设备上并不存在我们需要的数据表,所以需要等待数据表的创建完成,以防止在进入页面时直接对表进行操作时发生异常。
在 main
函数中执行 MySqlite
.forFeature
(),等待数据库初始化完成并且所有的表都已经创建完成后,再执行下面的代码:
// https
://www
.huizhanii
.com
void
main
() async
{
await
MySqlite
.forFeature
();
runApp
(const
MyApp
());
}
需要注意的是,等待数据库和表的初始化完成需要一定的时间,这种方式会阻塞页面。如果表的数量很多,白屏时间会加长。可以将这个方法放在启动页中,等初始化完毕后再进入主页面。由于我的程序数据表并不多,所以我直接将它写在 main
函数中了。
此时,在页面中可以直接对数据库进行增删改查的操作了。
// https
://www
.huizhanii
.com
UserInfoEntity
userInfoEntity
= UserInfoEntity
.instan
();
userInfoEntity
.insert
({
"name
": "汇站",
"sex
": 1,
"phone
": "123456789",
});
userInfoEntity
.find
();
userInfoEntity
.update
();
userInfoEntity
.remove
({"id
": 1});
基类的完整代码
转载请注明:汇站网 » 二次封装 Sqlite
基类(Flutter
教程)