1,用户首选项
导入模块:
import { preferences } from '@kit.ArkData';
创建存储的名字:
options: preferences.Options = { name: 'agreementPG' };
创建操作的对象:
dataPreferences: preferences.Preferences = preferences.getPreferencesSync(getContext(), this.options);
存入数据(保存在内存当中,退出app数据重进会消失):
this.dataPreferences.putSync('agreement', 'true');
持久化存储(保存在内存当中,退出app数据重进不会消失): this.dataPreferences.flush();
读取数据:
this.dataPreferences.getSync('agreement', 'false')
2,数据库
键值型数据库
约束限制
-
设备协同数据库,针对每条记录,Key的长度≤896 Byte,Value的长度<4 MB。
-
单版本数据库,针对每条记录,Key的长度≤1 KB,Value的长度<4 MB。
-
每个应用程序最多支持同时打开16个键值型分布式数据库。
-
键值型数据库事件回调方法中不允许进行阻塞操作,例如修改UI组件。
若要使用键值型数据库,首先要获取一个KVManager实例,用于管理数据库对象。示例代码如下所示:
Stage模型示例:
// 导入模块
import { distributedKVStore } from '@kit.ArkData';
// Stage模型
import { window } from '@kit.ArkUI';
import { UIAbility } from '@kit.AbilityKit';
import { BusinessError } from '@kit.BasicServicesKit';
let kvManager: distributedKVStore.KVManager | undefined = undefined;
export default class EntryAbility extends UIAbility {
onCreate() {
let context = this.context;
const kvManagerConfig: distributedKVStore.KVManagerConfig = {
context: context,
bundleName: 'com.example.datamanagertest'
};
try {
// 创建KVManager实例
kvManager = distributedKVStore.createKVManager(kvManagerConfig);
console.info('Succeeded in creating KVManager.');
// 继续创建获取数据库
} catch (e) {
let error = e as BusinessError;
console.error(`Failed to create KVManager. Code:${error.code},message:${error.message}`);
}
}
}
if (kvManager !== undefined) {
kvManager = kvManager as distributedKVStore.KVManager;
//进行后续操作
//...
}
FA模型示例:
// 导入模块
import { distributedKVStore } from '@kit.ArkData';
// FA模型
import { featureAbility } from '@kit.AbilityKit';
import { BusinessError } from '@kit.BasicServicesKit';
let kvManager: distributedKVStore.KVManager | undefined = undefined;
let context = featureAbility.getContext(); // 获取context
const kvManagerConfig: distributedKVStore.KVManagerConfig = {
context: context,
bundleName: 'com.example.datamanagertest'
};
try {
kvManager = distributedKVStore.createKVManager(kvManagerConfig);
console.info('Succeeded in creating KVManager.');
// 继续创建获取数据库
} catch (e) {
let error = e as BusinessError;
console.error(`Failed to create KVManager. Code:${error.code},message:${error.message}`);
}
if (kvManager !== undefined) {
kvManager = kvManager as distributedKVStore.KVManager;
//进行后续操作
//...
}
创建并获取键值数据库。示例代码如下所示:
let kvStore: distributedKVStore.SingleKVStore | undefined = undefined;
try {
const options: distributedKVStore.Options = {
createIfMissing: true,
encrypt: false,
backup: false,
autoSync: false,
// kvStoreType不填时,默认创建多设备协同数据库
kvStoreType: distributedKVStore.KVStoreType.SINGLE_VERSION,
// 多设备协同数据库:kvStoreType: distributedKVStore.KVStoreType.DEVICE_COLLABORATION,
securityLevel: distributedKVStore.SecurityLevel.S1
};
kvManager.getKVStore<distributedKVStore.SingleKVStore>('storeId', options, (err, store: distributedKVStore.SingleKVStore) => {
if (err) {
console.error(`Failed to get KVStore: Code:${err.code},message:${err.message}`);
return;
}
console.info('Succeeded in getting KVStore.');
kvStore = store;
// 请确保获取到键值数据库实例后,再进行相关数据操作
});
} catch (e) {
let error = e as BusinessError;
console.error(`An unexpected error occurred. Code:${error.code},message:${error.message}`);
}
if (kvStore !== undefined) {
kvStore = kvStore as distributedKVStore.SingleKVStore;
//进行后续操作
//...
}
调用put()方法向键值数据库中插入数据。示例代码如下所示:
const KEY_TEST_STRING_ELEMENT = 'key_test_string';
const VALUE_TEST_STRING_ELEMENT = 'value_test_string';
try {
kvStore.put(KEY_TEST_STRING_ELEMENT, VALUE_TEST_STRING_ELEMENT, (err) => {
if (err !== undefined) {
console.error(`Failed to put data. Code:${err.code},message:${err.message}`);
return;
}
console.info('Succeeded in putting data.');
});
} catch (e) {
let error = e as BusinessError;
console.error(`An unexpected error occurred. Code:${error.code},message:${error.message}`);
}
调用get()方法获取指定键的值。示例代码如下所示:
try {
kvStore.put(KEY_TEST_STRING_ELEMENT, VALUE_TEST_STRING_ELEMENT, (err) => {
if (err !== undefined) {
console.error(`Failed to put data. Code:${err.code},message:${err.message}`);
return;
}
console.info('Succeeded in putting data.');
kvStore = kvStore as distributedKVStore.SingleKVStore;
kvStore.get(KEY_TEST_STRING_ELEMENT, (err, data) => {
if (err != undefined) {
console.error(`Failed to get data. Code:${err.code},message:${err.message}`);
return;
}
console.info(`Succeeded in getting data. Data:${data}`);
});
});
} catch (e) {
let error = e as BusinessError;
console.error(`Failed to get data. Code:${error.code},message:${error.message}`);
}
调用delete()方法删除指定键值的数据。示例代码如下所示:
try {
kvStore.put(KEY_TEST_STRING_ELEMENT, VALUE_TEST_STRING_ELEMENT, (err) => {
if (err !== undefined) {
console.error(`Failed to put data. Code:${err.code},message:${err.message}`);
return;
}
console.info('Succeeded in putting data.');
kvStore = kvStore as distributedKVStore.SingleKVStore;
kvStore.delete(KEY_TEST_STRING_ELEMENT, (err) => {
if (err !== undefined) {
console.error(`Failed to delete data. Code:${err.code},message:${err.message}`);
return;
}
console.info('Succeeded in deleting data.');
});
});
} catch (e) {
let error = e as BusinessError;
console.error(`An unexpected error occurred. Code:${error.code},message:${error.message}`);
}
关系型数据库
关系型数据库基于SQLite组件,适用于存储包含复杂关系数据的场景,比如一个班级的学生信息,需要包括姓名、学号、各科成绩等,又或者公司的雇员信息,需要包括姓名、工号、职位等,由于数据之间有较强的对应关系,复杂程度比键值型数据更高,此时需要使用关系型数据库来持久化保存数据。
约束限制
-
系统默认日志方式是WAL(Write Ahead Log)模式,系统默认落盘方式是FULL模式。
-
数据库中有4个读连接和1个写连接,线程获取到空闲读连接时,即可进行读取操作。当没有空闲读连接且有空闲写连接时,会将写连接当做读连接来使用。
-
为保证数据的准确性,数据库同一时间只能支持一个写操作。
-
当应用被卸载完成后,设备上的相关数据库文件及临时文件会被自动清除。
-
ArkTS侧支持的基本数据类型:number、string、二进制类型数据、boolean。
-
为保证插入并读取数据成功,建议一条数据不要超过2M。超出该大小,插入成功,读取失败。
使用关系型数据库实现数据持久化,需要获取一个RdbStore,其中包括建库、建表、升降级等操作。示例代码如下所示:
Stage模型示例:
import { relationalStore } from '@kit.ArkData'; // 导入模块
import { UIAbility } from '@kit.AbilityKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { window } from '@kit.ArkUI';
// 此处示例在Ability中实现,使用者也可以在其他合理场景中使用
class EntryAbility extends UIAbility {
onWindowStageCreate(windowStage: window.WindowStage) {
const STORE_CONFIG :relationalStore.StoreConfig= {
name: 'RdbTest.db', // 数据库文件名
securityLevel: relationalStore.SecurityLevel.S1, // 数据库安全级别
encrypt: false, // 可选参数,指定数据库是否加密,默认不加密
customDir: 'customDir/subCustomDir', // 可选参数,数据库自定义路径。数据库将在如下的目录结构中被创建:context.databaseDir + '/rdb/' + customDir,其中context.databaseDir是应用沙箱对应的路径,'/rdb/'表示创建的是关系型数据库,customDir表示自定义的路径。当此参数不填时,默认在本应用沙箱目录下创建RdbStore实例。
isReadOnly: false // 可选参数,指定数据库是否以只读方式打开。该参数默认为false,表示数据库可读可写。该参数为true时,只允许从数据库读取数据,不允许对数据库进行写操作,否则会返回错误码801。
};
// 判断数据库版本,如果不匹配则需进行升降级操作
// 假设当前数据库版本为3,表结构:EMPLOYEE (NAME, AGE, SALARY, CODES, IDENTITY)
const SQL_CREATE_TABLE = 'CREATE TABLE IF NOT EXISTS EMPLOYEE (ID INTEGER PRIMARY KEY AUTOINCREMENT, NAME TEXT NOT NULL, AGE INTEGER, SALARY REAL, CODES BLOB, IDENTITY UNLIMITED INT)'; // 建表Sql语句, IDENTITY为bigint类型,sql中指定类型为UNLIMITED INT
relationalStore.getRdbStore(this.context, STORE_CONFIG, (err, store) => {
if (err) {
console.error(`Failed to get RdbStore. Code:${err.code}, message:${err.message}`);
return;
}
console.info('Succeeded in getting RdbStore.');
// 当数据库创建时,数据库默认版本为0
if (store.version === 0) {
store.executeSql(SQL_CREATE_TABLE); // 创建数据表
// 设置数据库的版本,入参为大于0的整数
store.version = 3;
}
// 如果数据库版本不为0且和当前数据库版本不匹配,需要进行升降级操作
// 当数据库存在并假定版本为1时,例应用从某一版本升级到当前版本,数据库需要从1版本升级到2版本
if (store.version === 1) {
// version = 1:表结构:EMPLOYEE (NAME, SALARY, CODES, ADDRESS) => version = 2:表结构:EMPLOYEE (NAME, AGE, SALARY, CODES, ADDRESS)
if (store !== undefined) {
(store as relationalStore.RdbStore).executeSql('ALTER TABLE EMPLOYEE ADD COLUMN AGE INTEGER');
store.version = 2;
}
}
// 当数据库存在并假定版本为2时,例应用从某一版本升级到当前版本,数据库需要从2版本升级到3版本
if (store.version === 2) {
// version = 2:表结构:EMPLOYEE (NAME, AGE, SALARY, CODES, ADDRESS) => version = 3:表结构:EMPLOYEE (NAME, AGE, SALARY, CODES)
if (store !== undefined) {
(store as relationalStore.RdbStore).executeSql('ALTER TABLE EMPLOYEE DROP COLUMN ADDRESS TEXT');
store.version = 3;
}
}
});
// 请确保获取到RdbStore实例后,再进行数据库的增、删、改、查等操作
}
}
FA模型示例:
import { relationalStore } from '@kit.ArkData'; // 导入模块
import { featureAbility } from '@kit.AbilityKit';
import { BusinessError } from '@kit.BasicServicesKit';
let context = featureAbility.getContext();
const STORE_CONFIG :relationalStore.StoreConfig = {
name: 'RdbTest.db', // 数据库文件名
securityLevel: relationalStore.SecurityLevel.S1 // 数据库安全级别
};
// 假设当前数据库版本为3,表结构:EMPLOYEE (NAME, AGE, SALARY, CODES, IDENTITY)
const SQL_CREATE_TABLE = 'CREATE TABLE IF NOT EXISTS EMPLOYEE (ID INTEGER PRIMARY KEY AUTOINCREMENT, NAME TEXT NOT NULL, AGE INTEGER, SALARY REAL, CODES BLOB, IDENTITY UNLIMITED INT)'; // 建表Sql语句,IDENTITY为bigint类型,sql中指定类型为UNLIMITED INT
relationalStore.getRdbStore(context, STORE_CONFIG, (err, store) => {
if (err) {
console.error(`Failed to get RdbStore. Code:${err.code}, message:${err.message}`);
return;
}
console.info('Succeeded in getting RdbStore.');
// 当数据库创建时,数据库默认版本为0
if (store.version === 0) {
store.executeSql(SQL_CREATE_TABLE); // 创建数据表
// 设置数据库的版本,入参为大于0的整数
store.version = 3;
}
// 如果数据库版本不为0且和当前数据库版本不匹配,需要进行升降级操作
// 当数据库存在并假定版本为1时,例应用从某一版本升级到当前版本,数据库需要从1版本升级到2版本
if (store.version === 1) {
// version = 1:表结构:EMPLOYEE (NAME, SALARY, CODES, ADDRESS) => version = 2:表结构:EMPLOYEE (NAME, AGE, SALARY, CODES, ADDRESS)
store.executeSql('ALTER TABLE EMPLOYEE ADD COLUMN AGE INTEGER');
store.version = 2;
}
// 当数据库存在并假定版本为2时,例应用从某一版本升级到当前版本,数据库需要从2版本升级到3版本
if (store.version === 2) {
// version = 2:表结构:EMPLOYEE (NAME, AGE, SALARY, CODES, ADDRESS) => version = 3:表结构:EMPLOYEE (NAME, AGE, SALARY, CODES)
store.executeSql('ALTER TABLE EMPLOYEE DROP COLUMN ADDRESS TEXT');
store.version = 3;
}
});
// 请确保获取到RdbStore实例后,再进行数据库的增、删、改、查等操作
获取到RdbStore后,调用insert()接口插入数据。示例代码如下所示:
let store: relationalStore.RdbStore | undefined = undefined;
let value1 = 'Lisa';
let value2 = 18;
let value3 = 100.5;
let value4 = new Uint8Array([1, 2, 3, 4, 5]);
let value5 = BigInt('15822401018187971961171');
// 以下三种方式可用
const valueBucket1: relationalStore.ValuesBucket = {
'NAME': value1,
'AGE': value2,
'SALARY': value3,
'CODES': value4,
'IDENTITY': value5,
};
const valueBucket2: relationalStore.ValuesBucket = {
NAME: value1,
AGE: value2,
SALARY: value3,
CODES: value4,
IDENTITY: value5,
};
const valueBucket3: relationalStore.ValuesBucket = {
"NAME": value1,
"AGE": value2,
"SALARY": value3,
"CODES": value4,
"IDENTITY": value5,
};
if (store !== undefined) {
(store as relationalStore.RdbStore).insert('EMPLOYEE', valueBucket1, (err: BusinessError, rowId: number) => {
if (err) {
console.error(`Failed to insert data. Code:${err.code}, message:${err.message}`);
return;
}
console.info(`Succeeded in inserting data. rowId:${rowId}`);
})
}
根据谓词指定的实例对象,对数据进行修改或删除。
调用update()方法修改数据,调用delete()方法删除数据。示例代码如下所示:
let value6 = 'Rose';
let value7 = 22;
let value8 = 200.5;
let value9 = new Uint8Array([1, 2, 3, 4, 5]);
let value10 = BigInt('15822401018187971967863');
// 以下三种方式可用
const valueBucket4: relationalStore.ValuesBucket = {
'NAME': value6,
'AGE': value7,
'SALARY': value8,
'CODES': value9,
'IDENTITY': value10,
};
const valueBucket5: relationalStore.ValuesBucket = {
NAME: value6,
AGE: value7,
SALARY: value8,
CODES: value9,
IDENTITY: value10,
};
const valueBucket6: relationalStore.ValuesBucket = {
"NAME": value6,
"AGE": value7,
"SALARY": value8,
"CODES": value9,
"IDENTITY": value10,
};
// 修改数据
let predicates1 = new relationalStore.RdbPredicates('EMPLOYEE'); // 创建表'EMPLOYEE'的predicates
predicates1.equalTo('NAME', 'Lisa'); // 匹配表'EMPLOYEE'中'NAME'为'Lisa'的字段
if (store !== undefined) {
(store as relationalStore.RdbStore).update(valueBucket4, predicates1, (err: BusinessError, rows: number) => {
if (err) {
console.error(`Failed to update data. Code:${err.code}, message:${err.message}`);
return;
}
console.info(`Succeeded in updating data. row count: ${rows}`);
})
}
// 删除数据
predicates1 = new relationalStore.RdbPredicates('EMPLOYEE');
predicates1.equalTo('NAME', 'Lisa');
if (store !== undefined) {
(store as relationalStore.RdbStore).delete(predicates1, (err: BusinessError, rows: number) => {
if (err) {
console.error(`Failed to delete data. Code:${err.code}, message:${err.message}`);
return;
}
console.info(`Delete rows: ${rows}`);
})
}
根据谓词指定的查询条件查找数据。
调用query()方法查找数据,返回一个ResultSet结果集。示例代码如下所示:
let predicates2 = new relationalStore.RdbPredicates('EMPLOYEE');
predicates2.equalTo('NAME', 'Rose');
if (store !== undefined) {
(store as relationalStore.RdbStore).query(predicates2, ['ID', 'NAME', 'AGE', 'SALARY', 'IDENTITY'], (err: BusinessError, resultSet) => {
if (err) {
console.error(`Failed to query data. Code:${err.code}, message:${err.message}`);
return;
}
console.info(`ResultSet column names: ${resultSet.columnNames}, column count: ${resultSet.columnCount}`);
// resultSet是一个数据集合的游标,默认指向第-1个记录,有效的数据从0开始。
while (resultSet.goToNextRow()) {
const id = resultSet.getLong(resultSet.getColumnIndex('ID'));
const name = resultSet.getString(resultSet.getColumnIndex('NAME'));
const age = resultSet.getLong(resultSet.getColumnIndex('AGE'));
const salary = resultSet.getDouble(resultSet.getColumnIndex('SALARY'));
const identity = resultSet.getValue(resultSet.getColumnIndex('IDENTITY'));
console.info(`id=${id}, name=${name}, age=${age}, salary=${salary}, identity=${identity}`);
}
// 释放数据集的内存
resultSet.close();
})
}
在同路径下备份数据库。示例代码如下所示:
if (store !== undefined) {
// "Backup.db"为备份数据库文件名,默认在RdbStore同路径下备份。也可指定路径:customDir + "backup.db"
(store as relationalStore.RdbStore).backup("Backup.db", (err: BusinessError) => {
if (err) {
console.error(`Failed to backup RdbStore. Code:${err.code}, message:${err.message}`);
return;
}
console.info(`Succeeded in backing up RdbStore.`);
})
}
在同路径下备份数据库。示例代码如下所示:
if (store !== undefined) {
// "Backup.db"为备份数据库文件名,默认在RdbStore同路径下备份。也可指定路径:customDir + "backup.db"
(store as relationalStore.RdbStore).backup("Backup.db", (err: BusinessError) => {
if (err) {
console.error(`Failed to backup RdbStore. Code:${err.code}, message:${err.message}`);
return;
}
console.info(`Succeeded in backing up RdbStore.`);
})
}
从备份数据库中恢复数据。示例代码如下所示:
if (store !== undefined) {
(store as relationalStore.RdbStore).restore("Backup.db", (err: BusinessError) => {
if (err) {
console.error(`Failed to restore RdbStore. Code:${err.code}, message:${err.message}`);
return;
}
console.info(`Succeeded in restoring RdbStore.`);
})
}
若数据库文件损坏,需要重建数据库。
进行开库及增删改查等操作时抛出错误码14800011表示数据库文件损坏。重建数据库的示例代码如下所示:
if (store !== undefined) {
// 数据库文件损坏后需要关闭所有数据库连接和结果集,使用store.close()方法或把对象置为null
(store as relationalStore.RdbStore).close();
store = undefined;
// 将config.allowRebuild配置为true,重新调用getRdbStore开库
const STORE_CONFIG: relationalStore.StoreConfig = {
name: 'RdbTest.db',
securityLevel: relationalStore.SecurityLevel.S1,
allowRebuild: true
};
relationalStore.getRdbStore(this.context, STORE_CONFIG).then(async (rdbStore: relationalStore.RdbStore) => {
store = rdbStore;
console.info('Get RdbStore successfully.')
}).catch((err: BusinessError) => {
console.error(`Get RdbStore failed, code is ${err.code},message is ${err.message}`);
})
if (store !== undefined) {
// 查看重建结果
if ((store as relationalStore.RdbStore).rebuilt === relationalStore.RebuildType.REBUILT) {
console.info('Succeeded in rebuilding RdbStore.');
// 将损坏前备份的数据恢复到新数据库中
(store as relationalStore.RdbStore).restore("Backup.db", (err: BusinessError) => {
if (err) {
console.error(`Failed to restore RdbStore. Code:${err.code}, message:${err.message}`);
return;
}
console.info(`Succeeded in restoring RdbStore.`);
})
}
}
}
删除数据库。
调用deleteRdbStore()方法,删除数据库及数据库相关文件。示例代码如下:
Stage模型示例:
relationalStore.deleteRdbStore(this.context, 'RdbTest.db', (err: BusinessError) => {
if (err) {
console.error(`Failed to delete RdbStore. Code:${err.code}, message:${err.message}`);
return;
}
console.info('Succeeded in deleting RdbStore.');
});
FA模型示例:
relationalStore.deleteRdbStore(context, 'RdbTest.db', (err: BusinessError) => {
if (err) {
console.error(`Failed to delete RdbStore. Code:${err.code}, message:${err.message}`);
return;
}
console.info('Succeeded in deleting RdbStore.');
});
3,通过PersistentStorage类
LocalStorage和AppStorage都是运行时的内存,但是在应用退出再次启动后,依然能保存选定的结果,是应用开发中十分常见的现象,这就需要用到PersistentStorage。
PersistentStorage是应用程序中的可选单例对象。此对象的作用是持久化存储选定的AppStorage属性,以确保这些属性在应用程序重新启动时的值与应用程序关闭时的值相同。
PersistentStorage将选定的AppStorage属性保留在设备磁盘上。应用程序通过API,以决定哪些AppStorage属性应借助PersistentStorage持久化。UI和业务逻辑不直接访问PersistentStorage中的属性,所有属性访问都是对AppStorage的访问,AppStorage中的更改会自动同步到PersistentStorage。
PersistentStorage和AppStorage中的属性建立双向同步。应用开发通常通过AppStorage访问PersistentStorage,另外还有一些接口可以用于管理持久化属性,但是业务逻辑始终是通过AppStorage获取和设置属性的。
PersistentStorage允许的类型和值有:
- number, string, boolean, enum 等简单类型。
- 可以被JSON.stringify()和JSON.parse()重构的对象,以及对象的属性方法不支持持久化。
- API12及以上支持Map类型,可以观察到Map整体的赋值,同时可通过调用Map的接口set, clear, delete 更新Map的值。且更新的值被持久化存储。详见装饰Map类型变量。
- API12及以上支持Set类型,可以观察到Set整体的赋值,同时可通过调用Set的接口add, clear, delete 更新Set的值。且更新的值被持久化存储。详见装饰Set类型变量。
- API12及以上支持Date类型,可以观察到Date整体的赋值,同时可通过调用Date的接口setFullYear, setMonth, setDate, setHours, setMinutes, setSeconds, setMilliseconds, setTime, setUTCFullYear, setUTCMonth, setUTCDate, setUTCHours, setUTCMinutes, setUTCSeconds, setUTCMilliseconds 更新Date的属性。且更新的值被持久化存储。详见装饰Date类型变量。
- API12及以上支持undefined 和 null。
- API12及以上支持联合类型。
PersistentStorage不允许的类型和值有:
- 不支持嵌套对象(对象数组,对象的属性是对象等)。因为目前框架无法检测AppStorage中嵌套对象(包括数组)值的变化,所以无法写回到PersistentStorage中。
持久化数据是一个相对缓慢的操作,应用程序应避免以下情况:
-
持久化大型数据集。
-
持久化经常变化的变量。
PersistentStorage的持久化变量最好是小于2kb的数据,不要大量的数据持久化,因为PersistentStorage写入磁盘的操作是同步的,大量的数据本地化读写会同步在UI线程中执行,影响UI渲染性能。如果开发者需要存储大量的数据,建议使用数据库api。
PersistentStorage和UI实例相关联,持久化操作需要在UI实例初始化成功后(即loadContent传入的回调被调用时)才可以被调用,早于该时机调用会导致持久化失败。
从AppStorage中访问PersistentStorage初始化的属性
初始化PersistentStorage:
PersistentStorage.persistProp('aProp', 47);
在AppStorage获取对应属性:
AppStorage.get<number>('aProp'); // returns 47
或在组件内部定义:
@StorageLink('aProp') aProp: number = 48;
完整代码如下:
PersistentStorage.persistProp('aProp', 47);
@Entry
@Component
struct Index {
@State message: string = 'Hello World'
@StorageLink('aProp') aProp: number = 48
build() {
Row() {
Column() {
Text(this.message)
// 应用退出时会保存当前结果。重新启动后,会显示上一次的保存结果
Text(`${this.aProp}`)
.onClick(() => {
this.aProp += 1;
})
}
}
}
}