1# 使用UI上下文接口操作界面(UIContext)
2
3## 概述
4
5OpenHarmony支持Stage模型后,存在一个ArkTS引擎里面运行多个ArkUI实例的场景。此时,一个ArkTS引擎下可能会有多个Ability,每个Ability可能有多个Window,每个Window通过loadContent加载页面,生成一个UIContent(ArkUI实例)。
6
7**图1** 多实例关系图
8![multi-instance](figures/multi-instance.png)
9
10FA模型默认只支持一个ArkUI实例,没有多实例的场景。当框架切换到Stage模型后,在FA模型下开放的ArkUI全局接口,在调用时无法明确运行在哪个实例里,存在语义不明确的问题。并且,这些接口实现依赖了ArkUI实例相关的信息,如果实例不明确,会导致运行时会出现预期外的行为。
11
12为了解决此类问题,ArkUI针对Stage模型推出了替代接口,以便满足开发者在多实例场景下的诉求。可使用window的接口方法[getUIContext](../reference/apis-arkui/js-apis-window.md#getuicontext10)或者使用组件内置方法[getUIContext](../reference/apis-arkui/arkui-ts/ts-custom-component-api.md#getuicontext)直接获取当前组件所在的UIContext,并使用[UIContext](../reference/apis-arkui/js-apis-arkui-UIContext.md#uicontext)中对应的接口获取与实例绑定的对象。
13
14## 接口替代关系
15
16部分多实例替代接口如下表所示,UIContext实例支持的全量接口以[UIContext](../reference/apis-arkui/js-apis-arkui-UIContext.md)中描述为准。
17
18|               全局接口                |               替代接口                |            说明            |
19| :-----------------------------------: | :-----------------------------------: | :------------------------: |
20|            @ohos.animator             |            createAnimator             |      自定义动画控制器      |
21|     @ohos.arkui.componentSnapshot     |         getComponentSnapshot          |          组件截图          |
22|      @ohos.arkui.componentUtils       |           getComponentUtils           |         组件工具类         |
23|      @ohos.arkui.dragController       |           getDragController           |         拖拽控制器         |
24|         @ohos.arkui.inspector         |            getUIInspector             |        组件布局回调        |
25|         @ohos.arkui.observer          |             getUIObserver             |          无感监听          |
26|              @ohos.font               |                getFont                |         自定义字体         |
27|             @ohos.measure             |            getMeasureUtil             |          文本计算          |
28|           @ohos.mediaquery            |             getMediaQuery             |          媒体查询          |
29|          @ohos.promptAction           |            getPromptAction            |            弹窗            |
30|             @ohos.router              |               getRouter               |          页面路由          |
31|              AlertDialog              |            showAlertDialog            |          警告弹窗          |
32|              ActionSheet              |            showActionSheet            |        列表选择弹窗        |
33|         CalendarPickerDialog          |                不支持                 |       日历选择器弹窗       |
34|           DatePickerDialog            |         showDatePickerDialog          |      日期滑动选择弹窗      |
35|           TimePickerDialog            |         showTimePickerDialog          |     时间滑动选择器弹窗     |
36|           TextPickerDialog            |         showTextPickerDialog          |     文本滑动选择器弹窗     |
37|              ContextMenu              |       getContextMenuController        |          菜单控制          |
38| vp2px/px2vp/fp2px/px2fp/lpx2px/px2lpx | vp2px/px2vp/fp2px/px2fp/lpx2px/px2lpx |        像素单位转换        |
39|             focusControl              |            getFocusControl            |          焦点控制          |
40|             cursorControl             |           getCursorControl            |          光标控制          |
41|              getContext               |            getHostContext             | 获取当前的Ability的Context |
42|        LocalStorage.getShared         |         getSharedLocalStorage         |  获取Ability传递的Storage  |
43|               animateTo               |               animateTo               |          显式动画          |
44|         animateToImmediately          |                不支持                 |        显式立即动画        |
45
46## 接口切换方法
47
48下述示例,实现了在具体窗口内弹出Toast。ArkUI可感知到是在当前页面下调用,找到对应的UI实例。但是,如果一些复杂场景的起始调用不在页面中,经过了异步调用,作用的实例就可能出现行为不明确的问题。
49
50```ts
51import { promptAction } from '@kit.ArkUI'
52
53@Entry
54@Component
55struct Index {
56  build() {
57    Row() {
58      Button()
59        .onClick(() => {
60          promptAction.showToast({
61            message: 'Message Info',
62            duration: 2000
63          });
64        })
65    }
66  }
67}
68```
69下述示例,callNative是Node-API方法,回调如果是由C侧异步触发,执行时无法感知当前页面信息,无法确定响应的UI实例。
70
71```ts
72import { promptAction } from '@kit.ArkUI'
73
74@Entry
75@Component
76struct Index {
77  build() {
78    Row() {
79      Button()
80        .onClick(() => {
81          bridge.callNative("xxxx", ()=> {
82            promptAction.showToast({
83              message: 'Message Info',
84              duration: 2000
85            });
86          })
87        })
88    }
89  }
90}
91```
92
93针对上述问题,可使用组件内置方法[`getUIContext`](../reference/apis-arkui/arkui-ts/ts-custom-component-api.md#getuicontext)直接获取当前组件所在的UIContext,并使用[UIContext](../reference/apis-arkui/js-apis-arkui-UIContext.md#uicontext)中的的getPromptAction接口获取与实例绑定的对象,使得Toast绑定到具体的实例。
94```ts
95@Entry
96@Component
97struct Index {
98  build() {
99    Row() {
100      Button()
101        .onClick(() => {
102          let uiContext = this.getUIContext();
103          let prompt = uiContext.getPromptAction();
104          bridge.callNative("xxxx", ()=> {
105            prompt.showToast({
106              message: 'Message Info',
107              duration: 2000
108            });
109          })
110        })
111    }
112  }
113}
114```
115
116对于UIContext中没有提供替代的接口(例如,CalendarPickerDialog和animateToImmediately),或者开发者自定义实现的业务行为与多实例相关,需要和实例绑定事(例如,一个代码段),可以使用[UIContext](../reference/apis-arkui/js-apis-arkui-UIContext.md#uicontext)的runScopedTask方法将接口或一段代码段包裹起来。
117
118| UIContext接口 | 说明                 |
119| ------------- | -------------------- |
120| runScopedTask | 执行绑定实例的闭包。 |
121
122上文的示例也可以使用如下方法实现。
123
124```ts
125// 执行绑定实例的闭包
126import { promptAction } from '@kit.ArkUI'
127
128@Entry
129@Component
130struct Index {
131  build() {
132    Row() {
133      Button()
134        .onClick(() => {
135          let uiContext = this.getUIContext();
136          uiContext.runScopedTask(() => {
137            promptAction.showToast({
138              message: 'Message Info',
139              duration: 2000
140            });
141          })
142        })
143    }
144  }
145}
146```
147