flutter-持久化储存、JSON与对象转化
前言
在开发过程中,无论是用户信息保存,还是网络数据保存,难免会用到本地操作,在flutter
中有一款 key-value
形式的本地操作(就像 ios
的 NSUserDefaults
似的)
另外,这里也介绍下JSON与对象间的相互转化
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互转
才是本章最主要的介绍
转载自:https://juejin.cn/post/7074571152500211719