我們平時(shí)開發(fā)android或者ios都有比較成熟的高級(jí)數(shù)據(jù)庫(kù)管理到腥,但是目前flutter暫時(shí)沒(méi)有账锹,所以我們目前數(shù)據(jù)存儲(chǔ)采用的是還是相對(duì)原生的sqflite萌业。
先上工具類:
import 'package:path/path.dart';
import 'package:sqflite/sqflite.dart';
import 'package:sqflite/sqlite_api.dart';
import 'package:yxk_app/utils/data_utils.dart';
import 'package:yxk_app/utils/log_utils.dart';
import 'db_bean_base.dart';
/// 數(shù)據(jù)庫(kù)存儲(chǔ)
class DbUtils {
DbUtils._();
// 數(shù)據(jù)庫(kù)路徑
String databasesPath;
// 數(shù)據(jù)庫(kù)
Database database;
// 數(shù)據(jù)庫(kù)版本
int dbVersion = 1;
static DbUtils dbUtils;
static DbUtils getInstance() {
if (null == dbUtils) dbUtils = DbUtils._();
return dbUtils;
}
/// 打開數(shù)據(jù)庫(kù)
Future openDb(String dbName) async {
// 如果數(shù)據(jù)庫(kù)路徑不存在,賦值
if (null == databasesPath || databasesPath.isEmpty)
databasesPath = await getDatabasesPath();
// 如果數(shù)據(jù)庫(kù)存在奸柬,而且數(shù)據(jù)庫(kù)沒(méi)有關(guān)閉生年,先關(guān)閉數(shù)據(jù)庫(kù)
closeDb();
database = await openDatabase(join(databasesPath, dbName + '.db'),
version: dbVersion, onCreate: (Database db, int version) async {
// 用戶表
await db.execute(
'CREATE TABLE UserInfo (userName TEXT PRIMARY KEY, nickName TEXT, headImgUrl TEXT, phone TEXT, idCard TEXT, telephone TEXT, emailYear TEXT, birthday TEXT, year TEXT, bankCard TEXT, province TEXT, city TEXT, county TEXT, town TEXT, address TEXT, sex INTEGER, status INTEGER, poorNumberCard TEXT, openBank TEXT, relationUser TEXT, relationName TEXT, appRole TEXT, createTime TEXT, updateTime Text)');
// 收貨地址信息表
await db.execute(
'CREATE TABLE PickInfo (id TEXT PRIMARY KEY, userName TEXT, tel TEXT, receiver TEXT, province TEXT, city TEXT, county TEXT, address TEXT, status TEXT)');
}, onUpgrade: (Database db, int oldVersion, int newVersion) {
// 版本更新可能牽扯到重新插入表、刪除表廓奕、表中字段變更-具體更新相關(guān)sql語(yǔ)句進(jìn)行操作
});
}
// 插入數(shù)據(jù)
Future<void> insertItem<T extends DbBaseBean>(T t) async {
if (null == database || !database.isOpen) return;
Log.d("開始插入數(shù)據(jù):${t.toJson()}");
// 插入操作
await database.insert(
t.getTableName(),
t.toJson(),
conflictAlgorithm: ConflictAlgorithm.replace,
);
}
/// 刪除數(shù)據(jù)
Future<void> deleteItem<T extends DbBaseBean>(T t,
{String key, String value}) async {
if (null == database || !database.isOpen) return null;
// 刪除表
if (StringUtils.isEmpty(key) || StringUtils.isEmpty(value)) {
await database.delete(t.getTableName());
} else {
// 刪除數(shù)據(jù)
await database.delete(
t.getTableName(),
where: (key + " = ?"),
whereArgs: [value],
);
}
}
/// 更新數(shù)據(jù)
Future<void> updateItem<T extends DbBaseBean>(
T t, String key, String value) async {
if (null == database || !database.isOpen) return null;
// 更新數(shù)據(jù)
await database.update(
t.getTableName(),
t.toJson(),
where: (key + " = ?"),
whereArgs: [value],
);
}
// 查詢數(shù)據(jù)
Future<List<T>> queryItems<T extends DbBaseBean>(T t,
{String key = "", String value = ""}) async {
if (null == database || !database.isOpen) return null;
List<Map<String, dynamic>> maps = List();
// 列表數(shù)據(jù)
if (StringUtils.isEmpty(key) || StringUtils.isEmpty(value)) {
maps = await database.query(t.getTableName());
} else {
maps = await database.query(
t.getTableName(),
where: (key + " = ?"),
whereArgs: [value],
);
}
// map轉(zhuǎn)換為L(zhǎng)ist集合
return List.generate(maps.length, (i) {
return t.fromJson(maps[i]);
});
}
/// 關(guān)閉數(shù)據(jù)庫(kù)
closeDb() async {
// 如果數(shù)據(jù)庫(kù)存在抱婉,而且數(shù)據(jù)庫(kù)沒(méi)有關(guān)閉,先關(guān)閉數(shù)據(jù)庫(kù)
if (null != database && database.isOpen) {
await database.close();
database = null;
}
}
/// 刪除數(shù)據(jù)庫(kù)
deleteDb(String dbName) async {
// 如果數(shù)據(jù)庫(kù)路徑不存在桌粉,賦值
if (null == databasesPath || databasesPath.isEmpty)
databasesPath = await getDatabasesPath();
await deleteDatabase(join(databasesPath, dbName + '.db'));
}
}
我們里面引入一個(gè)DbBaseBean蒸绩,主要是為了便于采用泛型,統(tǒng)一工具類調(diào)用方法铃肯。
使用方法:所有需要存儲(chǔ)的表對(duì)應(yīng)的實(shí)體類繼承該對(duì)象患亿。
// 基礎(chǔ)bean,工具類操作依賴此bean
abstract class DbBaseBean {
/// 實(shí)體轉(zhuǎn)換Map
Map<String, dynamic> toJson();
/// map轉(zhuǎn)實(shí)體
DbBaseBean fromJson(Map<String, dynamic> map);
/// 關(guān)聯(lián)表名稱
String getTableName();
}
使用說(shuō)明
1.我們的方法大多都是async方法押逼,所以調(diào)用的時(shí)候一定要加上await
2.打開數(shù)據(jù)庫(kù)步藕、用戶切換:
假如有兩個(gè)用戶,用戶號(hào)分別是"周杰倫"挑格、"陳奕迅"
需要切換的時(shí)候直接調(diào)用
await DbUtils.getInstance().openDb("周杰倫");
3.工具類中增刪改查都有咙冗,只需要正常操作就可以了。
表關(guān)聯(lián)實(shí)體類的創(chuàng)建:
- 加入相關(guān)引用
dependencies:
json_annotation: ^3.0.0
analyzer: 0.38.2
dev_dependencies:
flutter_test:
sdk: flutter
build_runner: ^1.7.0
json_serializable: ^3.2.0 - 打開網(wǎng)頁(yè)對(duì)數(shù)據(jù)進(jìn)行序列化生成.g文件
https://caijinglong.github.io/json2dart/index.html - 執(zhí)行命令漂彤,生成需要的文件
Terminal運(yùn)行:fflutter packages pub run build_runner build --delete-conflicting-outputs(刪除后重建)