5分钟完成 Flutter 本地数据库存储功能 |8月更文挑战

1,023 阅读4分钟

这是我参与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文件夹:

image.png

base.db 数据库文件

image.png

是不是逻辑就明白了,仿写一下 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。

image.png

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下的数据库怎么用的疑问。写下来,记录一下,代码拙劣,大神勿喷,如果对大家有帮助,更是深感欣慰。