鸿蒙开发-想在多线程间共享色彩配置?sendableColorSpaceManager怎么用
本文介绍了HarmonyOS中支持多线程共享的色彩管理器sendableColorSpaceManager。与普通colorSpaceManager不同,它实现了ISendable接口,可在主线程、TaskPool和Worker间传递共享。文章对比了两者的使用场景:单线程操作使用普通版本,多线程批量处理(如滤镜、导出)必须使用可共享版本。详细说明了创建标准/自定义可共享色彩空间的方法,以及查询属性
多线程处理图片?色彩管理器也要能"共享"
上一篇我们聊了 colorSpaceManager,它能帮你创建和管理色彩空间。但有一个问题:如果你的照片编辑 APP 需要在后台线程处理大量图片(比如批量滤镜、批量导出),普通的 colorSpaceManager 创建出来的对象是不能跨线程传递的。
为什么呢?因为在 ArkTS 的并发模型里,不同线程之间的对象默认是隔离的,你不能直接把一个线程里创建的对象传给另一个线程用。如果你尝试这么做,运行时会报错。
HarmonyOS 提供了 sendableColorSpaceManager 这个模块来解决这个问题。它创建出来的色彩管理器实现了 ISendable 接口,可以在主线程、TaskPool、Worker 等并发实例之间传递,而且传递的方式是引用传递——也就是说,多个线程共享同一个对象,修改会互相影响。
导入模块
import { colorSpaceManager, sendableColorSpaceManager } from '@kit.ArkGraphics2D';
注意这里同时导入了两个模块。因为 sendableColorSpaceManager 的参数类型(比如 ColorSpace 枚举、ColorSpacePrimaries 接口)都定义在 colorSpaceManager 里,所以两个都要导入。
普通版与可共享版对比
下面是两种色彩管理器的使用场景对比:
创建标准可共享色彩空间
跟普通版本的用法几乎一样,只是把 colorSpaceManager.create 换成了 sendableColorSpaceManager.create:
import { colorSpaceManager, sendableColorSpaceManager } from '@kit.ArkGraphics2D';
let colorSpace: sendableColorSpaceManager.ColorSpaceManager;
colorSpace = sendableColorSpaceManager.create(colorSpaceManager.ColorSpace.SRGB);
这里有几个细节值得注意:
-
返回类型不同:普通版返回的是
colorSpaceManager.ColorSpaceManager,而这里返回的是sendableColorSpaceManager.ColorSpaceManager。虽然名字一样,但它们是不同的类型。可共享版本实现了ISendable接口,所以能跨线程传递。 -
参数来源相同:色彩空间的枚举值
ColorSpace还是来自colorSpaceManager,可共享版本并没有重新定义一套枚举。 -
UNKNOWN 和 CUSTOM 同样不能直接创建:跟普通版一样,这两个枚举值不能传给
create方法。
创建自定义可共享色彩空间
如果你需要处理自定义色彩空间的照片,也可以创建自定义的可共享色彩管理器:
import { colorSpaceManager, sendableColorSpaceManager } from '@kit.ArkGraphics2D';
let colorSpace: sendableColorSpaceManager.ColorSpaceManager;
let primaries: colorSpaceManager.ColorSpacePrimaries = {
redX: 0.1,
redY: 0.1,
greenX: 0.2,
greenY: 0.2,
blueX: 0.3,
blueY: 0.3,
whitePointX: 0.4,
whitePointY: 0.4
};
let gamma: number = 2.2;
colorSpace = sendableColorSpaceManager.create(primaries, gamma);
跟普通版完全一样的参数,只是调用的是 sendableColorSpaceManager.create。创建出来的对象同样继承了 ISendable,可以在多线程间共享。
查询属性:跟普通版一样的方法
可共享版本的 ColorSpaceManager 实例提供了跟普通版一样的属性查询方法,但 API 签名稍有不同。
获取色彩空间类型:
let spaceName: colorSpaceManager.ColorSpace = colorSpace.getColorSpaceName();
注意返回类型直接用了 colorSpaceManager.ColorSpace,没有 try-catch 的示例。在实际使用中,建议你还是加上错误处理。
获取白点值:
import { collections } from '@kit.ArkTS';
let point: collections.Array<number> = colorSpace.getWhitePoint();
这里有个小区别:可共享版本返回的是 collections.Array<number>,而不是普通的 Array<number>。collections.Array 是 ArkTS 提供的可共享数组类型,同样能在多线程间传递。使用时你需要额外导入 collections 模块。
获取 gamma 值:
let gamma: number = colorSpace.getGamma();
这个跟普通版完全一样,返回一个浮点数。
多线程批量处理流程
下面是使用 sendableColorSpaceManager 进行批量图片处理的典型流程:
实际场景:后台批量处理图片的色彩管理
想象一下这个场景:你的照片编辑 APP 有一个"批量导出"功能,用户选了 100 张照片,要全部转换成 SRGB 色彩空间后导出。这个过程如果在主线程做,UI 会卡死。所以你要用 TaskPool 来做。
使用 sendableColorSpaceManager 的流程是这样的:
在主线程创建可共享的色彩空间对象:
import { colorSpaceManager, sendableColorSpaceManager } from '@kit.ArkGraphics2D';
// 创建一个 SRGB 色彩空间,用于批量导出
let targetColorSpace = sendableColorSpaceManager.create(colorSpaceManager.ColorSpace.SRGB);
把对象传给 TaskPool 的工作线程:
因为 targetColorSpace 实现了 ISendable 接口,你可以直接把它作为参数传给 TaskPool 的任务。在工作线程里,你可以直接使用这个对象来做色彩空间转换,不需要重新创建。
在工作线程里使用:
工作线程拿到这个对象后,可以调用 getColorSpaceName() 来确认目标色彩空间类型,然后对每张图片做转换。
什么时候该用可共享版本?
简单说,如果你的色彩管理器只在主线程用,就用普通的 colorSpaceManager;如果需要在多个线程间共享,就用 sendableColorSpaceManager。
具体来说:
- 单线程场景:普通的照片编辑、滤镜预览、色彩空间显示等,用
colorSpaceManager就够了。 - 多线程场景:批量图片处理、后台导出、TaskPool/Worker 中的色彩转换等,必须用
sendableColorSpaceManager。
性能方面,可共享版本因为要支持跨线程引用传递,可能会有轻微的额外开销。但对于色彩管理这种操作频率不高的场景,这个开销完全可以忽略。
小结
sendableColorSpaceManager 本质上就是 colorSpaceManager 的多线程安全版本。它的 API 设计几乎一模一样,区别就是创建出来的对象可以跨线程共享。如果你的 APP 有多线程处理图片的需求,记得用它来替代普通的色彩管理器。
最后提醒一下:因为是引用传递,多个线程共享同一个对象,所以如果你在一个线程里修改了对象的状态(虽然目前的 API 都是只读的),其他线程会立即看到变化。在设计并发逻辑时要注意这一点。
更多推荐



所有评论(0)