Flutter 的数据持久化有三种方式:
键值对 shared_preferences
读写文件 path_provider
数据库 sqflite
预备知识 Dart 库中包含许多返回 Future 或 Stream 对象的函数. 这些函数在设置完耗时任务(例如 I/O 操作)后, 就立即返回了,不会等待耗任务完成。 使用 async 和 await 关键字实现异步编程。 可以让像编写同步代码一样实现异步操作。
1 2 3 4 Future checkVersion() async { var version = await lookUpVersion(); // Do something with version }
必须要在 异步函数 ,也就是 asycn 标记的函数中,才可以使用 awiat。 并且在一个异步函数中,可以多次使用 await。
在 await 表达式中, 表达式的值通常是一个 Future 对象; 如果不是,这是表达式的值会被自动包装成一个 Future 对象。 Future 对象指明返回一个对象的承诺(promise)。 await 表达式执行的结果为这个返回的对象。 await 表达式会阻塞代码的执行,直到需要的对象返回为止。
键值对 —— shared_preferences 一个简单、异步的持久化 key-value 存储系统。在 iOS上 包装 NSUserDefaures,在 Android 上包装 SharedPreferences。
数据可能会被异步持久化到磁盘上,并且不能保证写操作返回后数据必然持久化到磁盘上,所以这个插件不能用于存储关键数据。
支持的类型
int
double
bool
String
List
安装
在 pubspec.yaml 中增加依赖。然后执行 flutter pub get
1 2 dependencies: shared_preferences: ^2.0.0
使用时,导入包
1 import 'package:shared_preferences/shared_preferences.dart'
使用 存储 1 2 3 4 5 6 7 8 9 10 11 12 13 14 void set(String key, value) async { SharedPreferences prefs = await SharedPreferences.getInstance(); if (value is String) { prefs.setString(key, value); } else if (value is num) { prefs.setInt(key, value); } else if (value is double) { prefs.setDouble(key, value); } else if (value is bool) { prefs.setBool(key, value); } else if (value is List) { prefs.setStringList(key, value.cast<String>()); } }
取值 1 2 3 4 5 Object? get(String key, [dynamic replace]) async { SharedPreferences prefs = await SharedPreferences.getInstance(); var data = prefs.get(key); return data ?? replace ?? null; }
移除 1 2 3 4 5 6 7 8 9 void remove(String key) async { SharedPreferences prefs = await SharedPreferences.getInstance(); prefs.remove(key); } void removeAll() async { SharedPreferences prefs = await SharedPreferences.getInstance(); prefs.clear(); }
读写文件 —— path_provider & dart:io path_provider 提供了一种平台透明的方式来访问设备文件系统上的常用存储位置。
dart:io 包含了文件读写的相关类,它属于 Dart 语法标准的一部分.
安装
在 pubspec.yaml 中增加依赖。然后执行 flutter pub get
1 2 dependencies: path_provider: ^2.0.0
使用时,导入包
1 import 'package:shared_preferences/shared_preferences.dart'
使用 文件夹目录 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 /// 获取临时目录路径 Future<String> _getLocalTemporaryPath() async { Directory dir = await getTemporaryDirectory(); return dir.path; } /// 获取应用程序目录路径 Future<String> _getLocalSupportPath() async { Directory dir = await getApplicationSupportDirectory(); return dir.path; } /// 获取文档目录路径 Future<String> _getLocalDocumentPath() async { Directory dir = await getApplicationDocumentsDirectory(); return dir.path; } /// 获取 Library 路径 Future<String> _getLocalLibraryPath() async { Directory dir = await getLibraryDirectory(); return dir.path; }
存储 1 2 3 4 5 6 7 8 9 10 11 12 13 14 Future<void> writeString(String value) async { try { // 获取本地目录路径 final filePath = awite _getLocalTemporaryPath(); // 找到本地目录下的文件 File file = File('${filePath}/str.txt'); // 执行写入操作 awite file.writeAsString(value); } catch(e) { } }
读取 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 Future<void> readString() async { try { // 获取本地目录路径 final filePath = awite _getLocalTemporaryPath(); // 找到本地目录下的文件 File file = File('${filePath}/str.txt'); // 执行读取操作 final result = await file.readAsString(); print("result-----$result"); } catch (e) { } }
数据库 —— sqflite
支持事务和批处理
打开过程中的自动版本管理
简易的插入/查询/更新/删除
可在 iOS 和 Android 后台线程执行 DB 操作
安装
在 pubspec.yaml 中增加依赖。然后执行 flutter pub get
使用时,导入包
1 import 'package:sqflite/sqflite.dart';
使用 创建本地数据库 1 2 3 4 5 6 7 8 9 final db = await openDatabase( join(await getDatabasePath(), 'sqlName'), version: 1, onCreate: (Database db, int version) async { await db.execute( 'CREATE TABLE Test (id INTEGER PRIMARY KEY, name TEXT, value INTEGER)' ); }, );
通过 getDatabasesPath() 函数获取到本地保存数据库文件的路径,在此路径后面拼接上我们的数据库文件名字,就是保存数据库文件的路径。在 iOS 中该路径在沙河路径下的 Documents 文件夹内,在 Android 中时默认数据库目录。
当调用 openDatabase 时,如果数据库不存在的话就会执行 onCreate 回调函数,所以我们可以把建表语句放在 onCreate 函数里。 除了 onCreate 回调,还有 onUpgrade、onDowngrade、onOpen 等回调。另外一个参数 singleInstance 它表示当传入相同的数据库路径是否返回同一个的实例对象,默认是 true。
插入数据 1 2 3 4 5 6 7 Future<void> insert(Map<String, Object> info) async { awiat db.inset( 'Test', info, conflictAlgorithm: ConflictAlgorithm.replace, // 冲突时,处理策略 ); }
删除数据 1 2 3 4 5 6 7 Future<void> delete(int uid) async { awiat db.delete( 'Test', where: 'id = ?', whereArgs: [uid], ); }
更新数据 1 2 3 4 5 6 7 8 Future<void> update(Map<String, Object> info) async { awiat db.update( 'Test', info, where: 'id = ?', whereArgs: [info['id']], ); }
查询数据 1 2 3 4 Future<List<Map<String, Object>>> query() async { final List<Map<tring, Object>> allInfos = awiat db.query('Test'); return allInfos; }
总结 本文简单记录了 flutter 的持久化存储的三种方式。具体的使用还是要贴近业务逻辑。在实际使用时,再查询官方的文档来补充学习。