1# IsolatedComponent (系统接口)
2
3IsolatedComponent用于支持在本页面内嵌入显示独立Abc(.abc文件)提供的UI,展示的内容在受限worker线程中运行。
4
5通常用于有Abc热更新诉求的模块化开发场景。
6
7> **说明:**
8>
9> 该组件从API Version 12开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。
10>
11> 本模块为系统接口。
12
13## 使用约束
14
15**规格约束**
16
171、本组件不支持预览。
18
192、Abc需要[VerifyAbc](../../apis-ability-kit/js-apis-bundleManager-sys.md#bundlemanagerverifyabc11)校验通过之后才可以使用于当前组件。
20
213、不支持构造参数更新,仅首次传入有效。
22
234、不支持IsolatedComponent组件嵌套场景。
24
25**体验约束**
26
271、创建IsolatedComponent组件时,受限worker线程加载Abc布局渲染存在一定耗时,在此等待期间显示IsolatedComponent组件的背景色。
28
292、主线程与受限worker线程之间布局渲染是异步处理,布局变化、旋转等导致的页面变化存在不同步现象。
30
313、主线程与受限worker线程之间事件传递是异步处理,不支持线程之间的事件冒泡,线程之间的UI交互存在事件冲突现象。
32
33**安全约束**
34
351、独立Abc通过IsolatedComponent组件嵌入式显示在宿主进程,即可说明其Abc内容完全向宿主开放,宿主有权操作独立Abc的内容,对此安全敏感场景禁用。
36
372、独立Abc运行在受限worker可保证相对安全,独立Abc内容不影响主线程。
38
39## 子组件
40
4142
43## 接口
44
45IsolatedComponent(options: IsolatedOptions)
46
47创建IsolatedComponent组件,用于显示受限worker运行的Abc。
48
49**参数:**
50
51| 参数名                | 参数类型                                                   | 必填 | 参数描述           |
52| --------------------- | ---------------------------------------------------------- | ---- | ------------------ |
53| options | [IsolatedOptions](#isolatedoptions)                | 是   | 需要传递的构造项。 |
54
55## IsolatedOptions
56用于在IsolatedComponent进行构造的时候,传递可选的构造参数。
57
58**参数:**
59
60| 参数名               | 参数类型                                 | 必填 | 参数描述                                                                                                      |
61| ----                 | ---------------------------------------- | ---- | ---------------                                                                                               |
62| want | [Want](../../apis-ability-kit/js-apis-app-ability-want.md)                                  | 是   | 要加载的Abc信息。 |
63| worker | [RestrictedWorker](../../apis-arkts/js-apis-worker-sys.md#restrictedworker11)       | 是   | 运行Abc的受限worker。 |
64
65## 属性
66仅支持[width](ts-universal-attributes-size.md#width)、[height](ts-universal-attributes-size.md#height)、[backgroundColor](ts-universal-attributes-background.md#backgroundcolor)通用属性
67
68## 事件
69
70不支持[通用事件](ts-universal-events-click.md)。
71
72将事件经过坐标转换后异步传递给受限worker线程处理。
73
74支持以下事件:
75
76### onError
77
78onError(callback:ErrorCallback)
79
80被拉起的Ability扩展在运行过程中发生异常时触发本回调。可通过回调参数中的code、name和message获取错误信息并做处理。
81
82**参数:**
83
84| 参数名                       | 类型   | 说明                                                         |
85| ---------------------------- | ------ | ------------------------------------------------------------ |
86| callback                        | [ErrorCallback](../../apis-basic-services-kit/js-apis-base.md#errorcallback) | 报错信息。    |
87
88## 示例(加载IsolatedComponent)
89
90本示例展示`IsolatedComponent`组件的基础使用方式,示例应用的`bundleName`为"com.example.isolateddemo",并使用本应用的Abc文件和extension页面作为嵌入展示的内容。构建应用项目后,具体测试步骤如下:
911. 在DevEco Studio上编译构建生成hap包,并安装到设备上;
922. 将本应用构建生成的modules.abc文件通过DevEco Studio或[hdc工具](../../../dfx/hdc.md)上传至应用沙箱路径`/data/app/el2/100/base/com.example.isolateddemo/haps/entry/files`下;
933. 打开应用页面,点击"verifyAbc"按钮进行校验,输出"VerifyAbc successfully"日志;
944. 点击"showIsolatedComponent"按钮,显示`IsolatedComponent`组件,内容为"Hello World"。
95
96- 受限worker脚本`ets/workers/OhCardWorker.ets`的内容如下:
97  ```ts
98  // OhCardWorker.ets
99  import { worker, ThreadWorkerGlobalScope, MessageEvents, ErrorEvent } from '@kit.ArkTS';
100  const workerPort: ThreadWorkerGlobalScope = worker.workerPort;
101
102  workerPort.onmessage = (e: MessageEvents) => {}
103  workerPort.onmessageerror = (e: MessageEvents) => {}
104  workerPort.onerror = (e: ErrorEvent) => {}
105  ```
106
107- 示例应用中`EntryAbility(UIAbility)`加载首页文件`ets/pages/Index.ets`的内容如下:
108  ```ts
109  import { worker } from '@kit.ArkTS';
110  import { bundleManager } from '@kit.AbilityKit';
111  import { BusinessError } from '@kit.BasicServicesKit';
112
113  // 对abc文件进行校验,并拷贝到指定沙箱路径下
114  function VerifyAbc(abcPaths: Array<string>, deleteOriginalFiles: boolean) {
115    try {
116      bundleManager.verifyAbc(abcPaths, deleteOriginalFiles, (err) => {
117        if (err) {
118          console.error("VerifyAbc failed, error message: " + err.message);
119        } else {
120          console.info("VerifyAbc successfully.");
121        }
122      });
123    } catch (err) {
124      let message = (err as BusinessError).message;
125      console.error("VerifyAbc failed, error message: " + message);
126    }
127  }
128
129  @Entry
130  @Component
131  struct Index {
132    @State isShow: boolean = false;
133    @State resourcePath: string = "";
134    @State abcPath: string = "";
135    @State entryPoint: string = "";
136    // abc文件名
137    private fileName: string = "modules";
138    // abc文件所属应用的bundleName
139    private bundleName: string = "com.example.isolateddemo";
140    // 受限worker
141    private worker ?: worker.RestrictedWorker = new worker.RestrictedWorker("entry/ets/workers/OhCardWorker.ets");
142
143    build() {
144      Row() {
145        Column() {
146          // 1.调用verifyAbc接口校验abc文件
147          Button("verifyAbc").onClick(() => {
148            let abcFilePath = `${getContext(this).filesDir}/${this.fileName}.abc`;
149            console.log("abcFilePath: " + abcFilePath);
150            VerifyAbc([abcFilePath], false);
151          }).height(100).width(100)
152
153          // 2.显示IsolatedComponent
154          Button("showIsolatedComponent").onClick(() => {
155            if (!this.isShow) {
156              // 资源路径
157              this.resourcePath = `${getContext(this).filesDir}/${this.fileName}.hap`;
158              // abc文件校验后的沙箱路径
159              this.abcPath = `/abcs${getContext(this).filesDir}/${this.fileName}`;
160              // 需要显示页面的入口路径
161              this.entryPoint = `${this.bundleName}/entry/ets/pages/extension`;
162              this.isShow = true;
163            }
164          }).height(100).width(100)
165
166          if (this.isShow) {
167            IsolatedComponent({
168              want: {
169                "parameters": {
170                  "resourcePath": this.resourcePath,
171                  "abcPath": this.abcPath,
172                  "entryPoint": this.entryPoint
173                }
174              },
175              worker: this.worker
176            })
177              .width(300)
178              .height(300)
179              .onError((err) => {
180                console.info("onError : " + JSON.stringify(err));
181              })
182          }
183        }
184        .width('100%')
185      }
186      .height('100%')
187    }
188  }
189  ```
190
191- 在受限worker线程中运行的入口页面文件`ets/pages/extension.ets`,需要在`resources/base/profile/main_pages.json`文件中配置该页面路径,其中内容如下:
192  ```ts
193  @Entry
194  @Component
195  struct Extension {
196    @State message: string = 'Hello World';
197
198    build() {
199      RelativeContainer() {
200        Text(this.message)
201          .id('HelloWorld')
202          .fontSize(50)
203          .fontWeight(FontWeight.Bold)
204          .alignRules({
205            center: { anchor: '__container__', align: VerticalAlign.Center },
206            middle: { anchor: '__container__', align: HorizontalAlign.Center }
207          })
208      }
209      .height('100%')
210      .width('100%')
211    }
212  }
213  ```
214
215- 在`module.json5`配置文件中增加`requestPermissions`标签,允许在受限模式下执行动态下发的方舟字节码:
216  ```json
217  "requestPermissions": [
218    {
219      "name": "ohos.permission.RUN_DYN_CODE",
220      "usedScene": {
221        "abilities": [
222          "EntryAbility"
223        ],
224        "when": "inuse"
225      }
226    }
227  ]
228  ```