这是我参与8月更文挑战的第6天,活动详情查看:8月更文挑战
废话开篇:APP下使用本地数据库一般多用于缓存搜索历史记录、新闻列表,目的是在无网络的情况下可以缓存一屏数据,虽然没有网络的情况下大部分功能用户是操作不了的,但是从体验上来说对用户是友好的。使用数据库搜索可以使搜索出来的结果为转换相应的model的json格式,这样用起来比较方便。其实iOS的本地缓存除了数据库还可以用归解档操作,但是没有搜索功能,只能存的是什么,取结果就是什么,不是很灵活。其实flutter的数据库操作也依赖与原生的文件处理,只是封装了更上层的api方便了开发使用。
步骤一、sqflite第三方库依赖添加
sqflite: ^2.0.0+3
flutter packages get
步骤二、sqflite的数据库初始化操作。
使用数据库前需要创建数据库db文件,只有创建好的db文件才能创建表、对表进行增删改查等操作。
//打开数据库
static Future<Database> _openDB() async {
Database db = await openDatabase('DB/base.db',onCreate:_onCreate,version: 1);
return db;
}
这里调用了 openDatabase 方法,第一个参数是db文件路径,第二个参数是创建数据库后需要执行的建表等操作。第三个参数是数据库版本号。下面一次解一下这三个参数。
1、db文件路径
这里虽说传入的是一个路径,但是“DB/base.db”前的文件地址是什么?这个问题就交给 path_provider 来回答。本身数据创建db文件内部是需要 path_provider 来作为依赖支持的,path_provider 会给出一个手机app的文件存储路径。那么,只需要在这个路径后添加上 DB/base.db 即可生成相应的文件。
path_provider 提供手机文件存储路径方法:
Directory document = await getApplicationDocumentsDirectory();
打印一下 document.path,下面输出就是文件默认存储路径,其实就是iOS下的Documents文件夹。
/Users/ganggu/Library/Developer/CoreSimulator/Devices/A5C799DF-DFA1-4186-954A-07CEBDE8FB77/data/Containers/Data/Application/7CA6AC43-3899-471C-8A03-94C81C6F13C4/Documents/
那么,刚才创建的db文件在哪呢?
DB文件夹:

base.db 数据库文件

是不是逻辑就明白了,仿写一下 openDatabase 创建文件的代码:
static Future<String> _createNewDB() async {
Directory document = await getApplicationDocumentsDirectory();
String path = join(document.path,'DB');
debugPrint('path = $path');
if(await new File(join(path,'base.db')).exists() == false){
try {
await new File(join(path,'base.db')).create(recursive: true);
debugPrint('创建数据库文件成功');
} catch(e){
debugPrint('创建数据库文件失败$e');
}
} else {
debugPrint('数据库文件已经存在');
}
return path;
}
说明一下:创建文件方法里面的 recursive 参数意义,就是如果前面的没有文件夹是要依次创建的,如果这里值为false,那么,就必须要保证路径前面所有的文件夹都是存在的。所以,这里赋值为true,当前面路径的某个文件夹没有的情况下会自动创建。
2、onCreate:创建数据库后需要执行的建表操作
这里仅创建了一个历史记录搜索表,column也只有一个就是keyword。

3、version:数据库版本。
最后添加一个关闭数据库的方法
//关闭数据库
static Future<void> _closeDB(Database db) async {
await db.close();
}
步骤三、增、删、改、查简单操作。
首先创建一个历史搜索记录类,为后面的数据操作提供数据模型。
class HistorySearchKeyWord {
String keyword;
HistorySearchKeyWord({required this.keyword});
Map<String,String> toMap(){
return {'keyword':this.keyword};
}
}
1、增
WSLDB.insertHistorySearchKeyWord(historySearchKeyWord: new HistorySearchKeyWord(keyword: '我爱大自然'));
//搜索记录插入操作
static Future<void> insertHistorySearchKeyWord({required HistorySearchKeyWord historySearchKeyWord}) async {
Database db = await _openDB();
await db.insert("search_keyword", historySearchKeyWord.toMap(),
conflictAlgorithm: ConflictAlgorithm.fail);
_closeDB(db);
}
2、删
WSLDB.deleteAllHistorySearchKeyWord();
//删除全部搜索记录
static deleteAllHistorySearchKeyWord() async {
Database db = await _openDB();
db.delete('search_keyword');
_closeDB(db);
}
db.delete 方法参数里还有 where、whereArgs 这两个参数是用来进行条件搜索的。
Future<int> delete(String table, {String? where, List<Object?>? whereArgs});
3、改
WSLDB.updateHistorySearchKeyWord(historySearchKeyWord: new HistorySearchKeyWord(keyword: '我很喜欢大自然'));
//更新搜索数据
static updateHistorySearchKeyWord({required HistorySearchKeyWord historySearchKeyWord}) async {
Database db = await _openDB();
db.update("search_keyword",historySearchKeyWord.toMap(),where: 'keyword = ?',whereArgs: ['我爱大自然'], conflictAlgorithm: ConflictAlgorithm.fail);
_closeDB(db);
}
4、查
WSLDB.selectAllHistorySearchKeyWord();
//搜索记录查询
static selectAllHistorySearchKeyWord() async {
Database db = await _openDB();
List<Map<String, dynamic>> result = await db.query('search_keyword',columns: ['keyword']);
result.forEach((Map<String, dynamic> e) {
debugPrint(e.toString());
});
_closeDB(db);
}
下面是查寻的参数集合,里面有查询的column、排序方式、查询条数限制等,可以根据业务场景进行操作。
Future<List<Map<String, Object?>>> query(String table,
{bool? distinct,
List<String>? columns,
String? where,
List<Object?>? whereArgs,
String? groupBy,
String? having,
String? orderBy,
int? limit,
int? offset});
好了,其实原生也好、flutter也好对于数据库的操作都是一样的,所以没有太多技术含量,纯属个人不同场景的使用总结,或许有的朋友也会有过flutter下的数据库怎么用的疑问。写下来,记录一下,代码拙劣,大神勿喷,如果对大家有帮助,更是深感欣慰。