
Worker线程和TaskPool线程的关于上下文context问题
数据库的context在不同线程情况下的内存不共享导致的数据库连接对象获取不一样(主线程UI线程和子线程)
代码:
/**
* 初始化数据库
*
* @param context 上下文
*/
public async initRdbStore(context: common.Context): Promise<void> {
logger.info(TAG, 'init rdbStore begin');
if (!context) {
logger.error(TAG, 'initRdbStore context is invalid');
return;
}
if (this.rdbStore) {
logger.info(TAG, 'rdbStore is exist');
return;
}
try {
this.rdbStore = await rdb.getRdbStore(context, STORE_CONFIG);
logger.info(TAG, 'getRdbStore succeed');
await this.createTable();
} catch (err) {
logger.info(TAG, `getRdbStore failed, err: ${err}`);
return;
}
}
分析原因:通过rdb.getRdbStore(context, STORE_CONFIG)去创建或者获取数据库的时候,需要上下文context,这个context需要全局或者获取的时候需要一致,因为这个原因我一开始没注意,使用了uiConetxt导致在不同的线程内获取到的数据库都是不一样的,导致数据库的curd都一样。
解决方法:
(1)通过appConext这个全局context去配置数据库,如:
const context: common.Context = getContext(this).getApplicationContext();
(2)还有一种方法就是通过把uiContext放进APPStorage里,如:
const uiContext: UIContext | undefined = AppStorage.get('uiContext');
参考链接:
二、static类属性和类方法在不同线程下内存不共享
static类属性和类方法在不同线程下内存内也不共享,解决方法就是加上@Sendable注解,通过调用传递的方式。
1. 支持string、number、boolean、bigint、null、undefined、Sendable class、collections容器集、ArkTSUtils.locks.AsyncLock、ArkTSUtils.SendableLruCache以及自定义的Sendable函数类型。
2. 禁止使用闭包变量,定义在顶层的Sendable class和Sendable function除外。
3. 不支持通过#定义私有属性,需用private。
4. 不支持计算属性。
代码样例:
@Sendable
class DatabaseConnection {
// 由于Sendable传输的时候有类型限制,所以下面传送的DatabaseConnection以及RdbStore会报错过不了编译
private static instance: DatabaseConnection | undefined = undefined;
public rdbStore: rdb.RdbStore | undefined = undefined;
}
如果你想传递一些基础属性就只能把属性命名在另一个传输类里面进行传输,基于数据库类里的变量不能有传输性质。
这个感觉和Record的属性有异曲同工之妙,用HashMap进行键值对的内存或者网络传输是不行的,只能用Record进行。
参考链接:
https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-sendable-module
疑问:为啥static类变量或者类方法作为类的属性不能共享内存,那这就和普通的类变量和类方法没啥区别了,为啥static属性不能做成共享呢?
ArkTS因为是线程安全的,我用了后端Java语言的线程不安全去想这个,所以static类对于声明自己的线程是可以用static属性所带来的便利。
