我們平時(shí)開發(fā)android或者ios都有比較成熟的高級數(shù)據(jù)庫管理,但是目前flutter暫時(shí)沒有,所以我們目前數(shù)據(jù)存儲采用的是還是相對原生的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ù)庫存儲
class DbUtils {
DbUtils._();
// 數(shù)據(jù)庫路徑
String databasesPath;
// 數(shù)據(jù)庫
Database database;
// 數(shù)據(jù)庫版本
int dbVersion = 1;
static DbUtils dbUtils;
static DbUtils getInstance() {
if (null == dbUtils) dbUtils = DbUtils._();
return dbUtils;
}
/// 打開數(shù)據(jù)庫
Future openDb(String dbName) async {
// 如果數(shù)據(jù)庫路徑不存在,賦值
if (null == databasesPath || databasesPath.isEmpty)
databasesPath = await getDatabasesPath();
// 如果數(shù)據(jù)庫存在,而且數(shù)據(jù)庫沒有關(guān)閉,先關(guān)閉數(shù)據(jù)庫
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語句進(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)換為List集合
return List.generate(maps.length, (i) {
return t.fromJson(maps[i]);
});
}
/// 關(guān)閉數(shù)據(jù)庫
closeDb() async {
// 如果數(shù)據(jù)庫存在,而且數(shù)據(jù)庫沒有關(guān)閉,先關(guān)閉數(shù)據(jù)庫
if (null != database && database.isOpen) {
await database.close();
database = null;
}
}
/// 刪除數(shù)據(jù)庫
deleteDb(String dbName) async {
// 如果數(shù)據(jù)庫路徑不存在,賦值
if (null == databasesPath || databasesPath.isEmpty)
databasesPath = await getDatabasesPath();
await deleteDatabase(join(databasesPath, dbName + '.db'));
}
}
我們里面引入一個(gè)DbBaseBean,主要是為了便于采用泛型,統(tǒng)一工具類調(diào)用方法。
使用方法:所有需要存儲的表對應(yīng)的實(shí)體類繼承該對象。
// 基礎(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();
}
使用說明
1.我們的方法大多都是async方法,所以調(diào)用的時(shí)候一定要加上await
2.打開數(shù)據(jù)庫、用戶切換:
假如有兩個(gè)用戶,用戶號分別是"周杰倫"、"陳奕迅"
需要切換的時(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)頁對數(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(刪除后重建)