前语
在开发过程中,无论是用户信息保存,还是网络数据保存,难免会用到本地操作,在flutter
中有一款 key-value
方式的本地操作(就像 ios
的 NSUserDefaults
似的)
另外,这儿也介绍下JSON与目标间的相互转化
JOSN快速生成各种语言Model入口
demo地址(内容在fileManager文件夹中,能够替换main中注释测验作用)
tips
:假如寄存很多数据,需求联系型数据库,那么能够搜其他资源
耐久化储存(key-value)
导入shared_preferences
这个耐久化储存用的仓库,是flutter的团队开发的,叫shared_preferences
,但他是以三方仓库存在的,因而需求手动导入
flutter pub add shared_preferences
导入之后就能够直接 import
直接运用了(一般运用提示导入)
import 'package:shared_preferences/shared_preferences.dart';
SharedPreferences介绍
SharedPreferences
为一个单例
,并且是一个 Future异步函数
,因而获取的时分也需求 Future异步函数调用获取
,经过 await
的方式获取到单例(前面有讲到过 Future)
大致原理
:与其他缓存三方原理类似,文件信息保存的时分内存一份、本地一份,在初始化的时分会一次性读取一切数据到内存
能够显着看出优缺点:访问速度快,内存占用大,适合小信息保存
假如寄存很多数据,或许需求寄存杂乱的数据,那么需求选择其他数据库
数据库
:对于联系型数据库SQLite、Core Data、GreenDao等;对于非联系型数据库,可选有Realm、UnQLite等;对于Key/Value存储,有比方Redis、Berkeley DB、Level DB等
能够根据自己的需求选择封装好的数据库,手机端一般是SQLite
和Realm
SharedPreferences读写操作
寄存数据
经过传递key
和value
,能寄存各种基本数据,发现没有寄存目标的(不后边介绍)
//这儿只是经过泛型演示,实际上用哪个调用哪个即可,能够自己封装一下
static saveInfo<T>(String key, T value) async {
//需求经过await获取单例目标
final manager = await SharedPreferences.getInstance();
//默许的运用只有如下几种
manager.setBool(key, value as bool);
manager.setDouble(key, value as double);
manager.setInt(key, value as int);
manager.setString(key, value as String);
manager.setStringList(key, value as List<String>);
}
读取数据
经过传递key
值,能够直接调用对应的get
办法即可,能够发现也没有读取目标的(后边介绍)
//这儿只是经过泛型演示,实际上用哪个调用哪个即可,能够自己封装一下
static Future<T> readInfo<T>(String key) async {
final manager = await SharedPreferences.getInstance();
return manager.getString(key) as T;
return manager.getBool(key) as T;
return manager.getDouble(key) as T;
return manager.getInt(key) as T;
return manager.getString(key) as T;
return manager.getStringList(key) as T;
}
删去数据
删去不多说了,传一个key就删了
static remove(String key) async {
final manager = await SharedPreferences.getInstance();
manager.remove(key);
}
json与目标相互转化与寄存目标
前面也看到了,shared_preferences
没有寄存目标的本事,那我们就寄存目标
变成 寄存json字符串
即可
因而,需求了解的过程便是 json与目标的相互转化
在 flutter
中现在还没有看到反射机制
,因而还无法友爱的一键式转化
,现在只能以 Map
作为纽带
, json
和 Map
之间的相互转化,目标所属类负责 目标
和Map
之间的相互转化
json和Map之间的转化
经过系统预制的 convert
库,来完成转化过程
经过 jsonEncode
将 Map
转化成 jsonString
final userMap = {
name: "Marshal",
age: 20
}
//将map转化成 jsonString
final jsonString = jsonEncode(userMap);
经过 jsonDecode
将 jsonString
转化成 Map
final jsonString = "{"name": "Marshal", "age": 20}";
//jsonString 转化成 Map
final jsonMap = jsonDecode(jsonString);
目标和Map之间的转化
以 UserInfo
类为例,创立两个办法(每个需求保存的类都要完成这两个办法)
jsonMap转化为目标
:经过命名式结构办法
,能够将传过来的 jsonMap
转化为 本目标
目标转化为jsonMap
:经过目标办法或许类办法,能够将本类创立的目标,转化为 Map
//选中类名,摁着 ctl + enter,生成 Constructor,选择需求默许初始化的特点,能够生成带参结构办法
class UserInfo {
String name;
int age;
UserInfo(this.name, this.age);
//命名式结构办法,也能够是用工厂结构办法
UserInfo.fromJson(Map<String, dynamic> json): name = json['name'], age = json['age'];
//假如想写成协议,归档(json和目标互转时,为了运用方便)时,能够承继协议,那么能够用普通办法,而不是结构办法
Map<String, dynamic> toJson() =>
{'name': name, 'age': age};
}
目标和json的直接相互转化
将目标
直接转化为json字符串
,以UserInfo
为例
final userInfo = UserInfo("Marshal", 20);
//将 UserInfo 转化为 jsonMap
final userMap = userInfo.toJson();
//然后调用 jsonEncode 将 map 转化成 jsonString
final jsonString = jsonEncode(userMap);
//jsonEncode默许只能将map转化成json,因而需求使用二个回调,将目标转化为map,然后才进行的转化
//实际和上面相同
final jsonString2 = jsonEncode(value,
toEncodable: (Object? value) => value is UserInfo
? value.toJson()
: throw UnsupportedError('Cannot convert to JSON: $value'));
将json字符串
直接转化为目标
,以UserInfo
为例
final jsonString = "{"name": "Marshal", "age": 20}";
//将 jsonString 转化为 jsonMap
final jsonMap = jsonDecode(jsonString); //转化成 Map
//将 jsonMap 转化为 UserInfo
final userInfo = UserInfo.fromJson(jsonMap);
SharedPreferences存取目标
寄存目标,将前面的过程都结合起来,寄存目标转化的json字符串
static saveObject(String key, UserInfo value) async {
final manager = await SharedPreferences.getInstance();
//实际上能够将 UserInfo设置为泛型束缚,承继(or多承继)某个类或许完成某一个接口,经过该接口调用toJson办法
//将一个类转化为jsonString
//此过程需求调用对应类的 toJson 办法,现将类信息放到 Map 中,然后在转化成json
final userMap = value.toJson();
//然后调用jsonEncode将map转化成 jsonString
final jsonString = jsonEncode(userMap);
//jsonEncode默许只能将map转化成json,因而需求使用二个回调,将目标转化为map,然后才进行的转化
//实际和上面相同
final jsonString2 = jsonEncode(value,
toEncodable: (Object? value) => value is UserInfo
? value.toJson()
: throw UnsupportedError('Cannot convert to JSON: $value'));
if (jsonString.isEmpty) return;
manager.setString(key, jsonString);
log('jsonEncode --' + jsonString);
}
读取目标,将前面的过程都结合起来,读取json字符串转化的目标
static Future<dynamic> readObject(String key) async {
final manager = await SharedPreferences.getInstance();
final jsonString = manager.getString(key);
if (jsonString != null) {
final jsonMap = jsonDecode(jsonString); //转化成 Map
log('jsonDecode --' + jsonMap.toString());
//实际运用中,能够直接回来 Map 调集,从外面给类赋值,以减少耦合
return UserInfo.fromJson(jsonMap); //根据根据命名式结构办法转化
}
return null;
}
tips
: FileManagerEx(存取目标改进版,现在无法处理结构办法的问题,只能略微约束一下,仅供参考哈)
最终
从速测试一下吧,这个 shared_preferences
只适合寄存少量数据,例如用户基本信息,查找信息等,假如需求很多数据,或许联系型,能够切换其他的哈
这个 目标和json互转
才是本章最主要的介绍