1# Transferable对象(NativeBinding对象)
2
3
4Transferable对象(也称为NativeBinding对象)指的是一个JS对象,绑定了一个C++对象,且主体功能由C++提供,其JS对象壳被分配在虚拟机本地堆(LocalHeap)。跨线程传输时可以直接复用同一个C++对象,相比于JS对象的拷贝模式,传输效率较高。因此,可共享或转移的NativeBinding对象也被称为Transferable对象。
5
6
7## 共享模式
8
9如果C++实现能够保证线程安全性,则这个NativeBinding对象的C++部分可以支持共享传输。此时,NativeBinding对象跨线程传输后,只需要重新创建JS壳,就可以桥接到相同的C++对象上。通信过程如下图所示:
10
11
12![nativeBinding](figures/nativeBinding.png)
13
14
15常见的共享模式NativeBinding对象包括Context,Context对象包含应用程序组件的上下文信息,它提供了一种访问系统服务和资源的方式,使得应用程序组件可以与系统进行交互。获取Context信息的方法可以参考[获取上下文信息](../application-models/application-context-stage.md)。
16
17示例可参考[使用TaskPool进行频繁数据库操作](./batch-database-operations-guide.md#使用taskpool进行频繁数据库操作)。
18
19
20## 转移模式
21
22如果C++实现包含了数据,且无法保证线程安全性,则这个NativeBinding对象的C++部分需要采用转移方式传输。此时,NativeBinding对象跨线程传输后,只需要重新创建JS壳,就可以桥接到C++对象上,不过原对象需要移除对此对象的绑定关系。通信过程如下图所示:
23
24![nativeBinding_transfer](figures/nativeBinding_transfer.png)
25
26常见的转移模式NativeBinding对象包括PixelMap,[PixelMap对象](../reference/apis-image-kit/js-apis-image.md#imagecreatepixelmap8)可以读取或写入图像数据以及获取图像信息,常用于在应用或系统中显示图片。
27
28### 使用示例
29
30这里提供了一个跨线程传递PixelMap对象的示例以帮助更好理解。首先获取rawfile文件夹中的图片资源,然后在子线程中创建PixelMap对象传递给主线程,具体实现如下:
31
32```ts
33// Index.ets
34import { taskpool } from '@kit.ArkTS';
35import { loadPixelMap } from './pixelMapTest';
36import { BusinessError } from '@kit.BasicServicesKit';
37
38@Entry
39@Component
40struct Index {
41  @State message: string = 'Hello World';
42  @State pixelMap: PixelMap | undefined = undefined;
43
44  private loadImageFromThread(): void {
45    const resourceMgr = getContext(this).resourceManager;
46    // 此处‘startIcon.png’为media下复制到rawfile文件夹中,请开发者自行替换,否则imageSource创建失败会导致后续无法正常执行。
47    resourceMgr.getRawFd('startIcon.png').then(rawFileDescriptor => {
48      taskpool.execute(loadPixelMap, rawFileDescriptor).then(pixelMap => {
49        if (pixelMap) {
50          this.pixelMap = pixelMap as PixelMap;
51          console.log('Succeeded in creating pixelMap.');
52          // 主线程释放pixelMap。由于子线程返回pixelMap时已调用setTransferDetached,所以此处能够立即释放pixelMap。
53          this.pixelMap.release();
54        } else {
55          console.error('Failed to create pixelMap.');
56        }
57      }).catch((e: BusinessError) => {
58        console.error('taskpool execute loadPixelMap failed. Code: ' + e.code + ', message: ' + e.message);
59      });
60    });
61  }
62
63  build() {
64    RelativeContainer() {
65      Text(this.message)
66        .id('HelloWorld')
67        .fontSize(50)
68        .fontWeight(FontWeight.Bold)
69        .alignRules({
70          center: { anchor: 'container', align: VerticalAlign.Center },
71          middle: { anchor: 'container', align: HorizontalAlign.Center }
72        })
73        .onClick(() => {
74          this.loadImageFromThread();
75        })
76    }
77    .height('100%')
78    .width('100%')
79  }
80}
81```
82
83```ts
84// pixelMapTest.ets
85import { image } from '@kit.ImageKit';
86
87@Concurrent
88export async function loadPixelMap(rawFileDescriptor: number): Promise<PixelMap> {
89  // 创建imageSource。
90  const imageSource = image.createImageSource(rawFileDescriptor);
91  // 创建pixelMap。
92  const pixelMap = imageSource.createPixelMapSync();
93  // 释放imageSource。
94  imageSource.release();
95  // 使pixelMap在跨线程传输完成后,断开原线程的引用。
96  pixelMap.setTransferDetached(true);
97  // 返回pixelMap给主线程。
98  return pixelMap;
99}
100```
101