# 17.3:数据持久化
用户登录后实现用户信息持久化操作,方便用户下次打开应用自动登录,用户在执行每一条计算表达式时自动执行持久化操作,方便后续查看计算记录。
# 17.3.1:用户信息持久化
ArkUI开发框架在 '@ohos.data.storage'
模块里提供了数据缓存的相关 API ,支持 key-value 键值对的轻量级存储, key
的为 string
类型, value
类型支持 number
、 string
和 boolean
。
用户信息持久化可以使用该 API 实现,代码如下所示:
import dataStorage from '@ohos.data.storage';
import featureAbility from '@ohos.ability.featureAbility';
import {Logger} from "./../../common/utils/Logger"
let STORAGE_FILE = "user_file";
let USER_INFO = "user_info";
export class User {
private static sInstance: User; // 全局User实例
public static get(): User {
if(null == User.sInstance) {
User.sInstance = new User();
}
return User.sInstance;
}
private id: string; // 用户id
private name: string; // 用户名
private token: string; // 和服务器验证的标识
private skinType: number; // 当前用户的皮肤类型
private constructor() {
this.init();
}
// 省略部分API
public toString() {
return JSON.stringify(User.get());
}
// 初始化用户数据
public init() {
featureAbility.getContext().getFilesDir((error, path) => {
if(path) {
var storage = dataStorage.getStorageSync(path + "/" + STORAGE_FILE);
if(storage) {
var value = storage.getSync(USER_INFO, "").toString();
if (value.length > 0) {
var json = JSON.parse(value);
this.setId(json.id).setToken(json.token).setSkinType(json.skinType).setName(json.name);
}
} else {
Logger.log("get storage invalid")
}
}
});
}
// 保存用户数据
public save() {
featureAbility.getContext().getFilesDir((error, path) => {
if(path) {
var storage = dataStorage.getStorageSync(path + "/" + STORAGE_FILE);
if(storage) {
storage.putSync(USER_INFO, this.toString());
storage.flushSync();
} else {
Logger.log("get storage invalid")
}
}
});
}
// 清空缓存数据
public clear() {
User.sInstance = new User();
featureAbility.getContext().getFilesDir((error, path) => {
if(path) {
var storage = dataStorage.getStorageSync(path + "/" + STORAGE_FILE);
if(storage) {
storage.clearSync();
} else {
Logger.log("get storage invalid")
}
}
});
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
User
添加了 clear()
, save()
和 init()
方法,这三个方法说明如下:
- init():从缓存数据中初始化用户信息。
- save():登录成功后,保存用户信息。
- clear(): 用户退出登录后,清楚缓存信息。
📢: '@ohos.data.storage'
模块提供的 Storage
接口对存储的数据有如下要求:
- 存储数量:
Storage
存储的数据是加载在内存中的,建议存储的数据不要超过 10000 条并及时清理不再使用的实例以便减少内存开销。 - 存储字段:
Storage
存储的字段有长度限制,key
为string
类型时,长度不超过 80 个字符。value
为string
类型时,长度不超过 8192 个字符并允许为空。
# 17.3.2:表达式持久化
'@ohos.data.storage'
模块提供的 Storage
接口对存储数据有要求并且用户计算数据比较大,因此计算表达式数据存储在数据库里是比较合适的。
ArkUI开发框架在 '@ohos.data.rdb'
模块里提供了基于 SQLite 组件的一套完整的对本地数据库进行管理的接口 RdbStore
,它对外提供了一系列的增、删、改、查等方法并同时支持运行 SQL 语句来满足复杂场景的需要。
创建 ExpressionManager
类,它负责对 Expression
数据的增、删、改、查等操作。代码如下:
import featureAbility from '@ohos.ability.featureAbility';
import rdb from '@ohos.data.rdb';
import {Expression} from "./../modules/expression"
import {Logger} from "./../../common/utils/Logger"
var INSTANCE: ExpressionManager = null;
let DB_NAME = "calculator.db";
let TB_NAME = "calculator_expression";
let COL_ID = "id";
let COL_OD = "ownerId";
let COL_EP = "expression";
let COL_RT = "result";
let COL_CM = "comment";
let COL_TM = "time";
let DB_CONFIG = { name: DB_NAME };
let CREATE_TABLE = "CREATE TABLE IF NOT EXISTS " + TB_NAME + " ( " +
COL_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
COL_OD + " INTEGER, " +
COL_EP + " TEXT, " +
COL_RT + " INTEGER, " +
COL_CM + " TEXT, " +
COL_TM + " INTEGER" +
")";
export class ExpressionManager {
public static init() {
ExpressionManager.get().initDB();
}
public static get() {
if(null == INSTANCE) {
INSTANCE = new ExpressionManager();
}
return INSTANCE;
}
private rdbStore: rdb.RdbStore;
private constructor() {
}
// 删除Expression
public deleteExpression(expression: Expression) {
if(expression && this.rdbStore) {
var sql = "delete from " + TB_NAME + " where " + COL_ID + " = " + expression.id;
this.rdbStore.executeSql(sql, null, (error, result) => {
if(error) {
Logger.log(JSON.stringify(error));
}
});
}
}
// 更新Expression
public updateExpression(expression: Expression) {
if(expression && this.rdbStore) {
var sql = "update " + TB_NAME + " " +
"set " +
COL_OD + " = " + expression.ownerId + ", " +
COL_EP + " = `" + expression.expression + "`, " +
COL_RT + " = " + expression.result + ", " +
COL_CM + " = `" + expression.comment + "`, " +
COL_TM + " = " + expression.time + " " +
"where " +
COL_ID + " = " + expression.id;
this.rdbStore.executeSql(sql, null, (error, result) => {
if(error) {
Logger.log(JSON.stringify(error));
}
});
}
}
// 保存Expression
public saveExpression(expression: Expression) {
if(expression && this.rdbStore) {
var sql = "insert into " + TB_NAME + " values(NULL, "
+ expression.ownerId + ", `"
+ expression.expression + "`, "
+ expression.result + ", `"
+ expression.comment + "`, "
+ expression.time
")";
this.rdbStore.executeSql(sql, null, (error, result) => {
if(error) {
Logger.log(JSON.stringify(error));
}
});
}
}
// 查询Expression
public queryExpression(id: number, callback: (data: Expression) => void) {
if(this.rdbStore) {
var sql = "select * from " + TB_NAME + " where id = " + id;
var value = null;
this.rdbStore.querySql(sql, null, (error, resultSet) => {
if(resultSet) {
if(resultSet.goToNextRow()) {
const id = resultSet.getLong(0);
const ownerId = resultSet.getLong(1);
const expression = resultSet.getString(2);
const result = resultSet.getLong(3);
const comment = resultSet.getString(4);
const time = resultSet.getLong(5);
value = new Expression(id, ownerId, expression, result, comment, time);
}
resultSet.close();
}
callback?.call(this, value);
});
}
}
// 查询所有Expression
public queryExpressions(callback: (data: Array<Expression>) => void) {
if(this.rdbStore) {
var sql = "select * from " + TB_NAME;
const array: Array<Expression> = new Array<Expression>();
this.rdbStore.querySql(sql, null, (error, resultSet) => {
if(resultSet) {
while(resultSet.goToNextRow()) {
const id = resultSet.getLong(0);
const ownerId = resultSet.getLong(1);
const expression = resultSet.getString(2);
const result = resultSet.getLong(3);
const comment = resultSet.getString(4);
const time = resultSet.getLong(5);
array.push(new Expression(id, ownerId, expression, result, comment, time));
}
resultSet.close();
}
callback?.call(this, array);
});
}
}
// APP 启动时,初始化DB
private initDB() {
rdb.getRdbStore(featureAbility.getContext(), DB_CONFIG, 1, (error, rdbStore) => {
if(rdbStore) {
this.rdbStore = rdbStore;
this.createDBIfNecessary();
} else {
Logger.log("get rdbStore failure");
}
})
}
private createDBIfNecessary() {
if(this.rdbStore) {
this.rdbStore.executeSql(CREATE_TABLE);
} else {
Logger.log("rdbStore invalid");
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
ExpressionManager
提供了对 Expression
的增删改查等操作,它内部缓存了 RdbStore
实例便于后续对 Expression
的修改,因此需要在 APP 启动时初始化 ExpressionManager
,APP 启动会回调 app.ets 的 onCreate()
方法,所以初始化代码如下所示:
import {ExpressionManager} from "./common/manager/expression_manager"
export default {
// APP启动,调用该方法
onCreate() {
console.info('Application onCreate')
ExpressionManager.init();
},
// APP销毁,调用该方法
onDestroy() {
console.info('Application onDestroy')
},
}
2
3
4
5
6
7
8
9
10
11
12
13
14
# 17.3.3:小结
本小结简单介绍了数据持久化的基本操作,另外用户信息借助 '@ohos.data.storage'
模块的方法实现本地存储,读者也可以把它存储在数据库里。本地存储的操作,笔者由于没有设备进行实际验证,可能会有异常发生,待笔者有设备后再做验证,也欢迎有设备的读者帮忙做下验证。