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