1# 通过router或call事件刷新卡片内容
2
3使用router事件,点击卡片可拉起对应应用的UIAbility至前台,并刷新卡片。使用call事件,点击卡片可拉起对应应用的UIAbility至后台,并刷新卡片。在卡片页面中可以通过[postCardAction](../reference/apis-arkui/js-apis-postCardAction.md#postcardaction)接口触发router事件或者call事件拉起UIAbility,然后由UIAbility刷新卡片内容,下面是这种刷新方式的简单示例。
4
5> **说明:**
6>
7> 本文主要介绍动态卡片的事件开发。对于静态卡片,请参见[FormLink](../reference/apis-arkui/arkui-ts/ts-container-formlink.md)。
8
9## 通过router事件刷新卡片内容
10
11- 在卡片页面代码文件中,通过注册Button的onClick点击事件回调并在回调中调用postCardAction接口,触发router事件拉起UIAbility至前台。
12
13  ```ts
14  let storageUpdateRouter = new LocalStorage();
15
16  @Entry(storageUpdateRouter)
17  @Component
18  struct WidgetUpdateRouterCard {
19    @LocalStorageProp('routerDetail') routerDetail: ResourceStr = $r('app.string.init');
20
21    build() {
22      Column() {
23        Column() {
24          Text(this.routerDetail)
25            .fontColor('#FFFFFF')
26            .opacity(0.9)
27            .fontSize(14)
28            .margin({ top: '8%', left: '10%', right: '10%' })
29            .textOverflow({ overflow: TextOverflow.Ellipsis })
30            .maxLines(2)
31        }.width('100%').height('50%')
32        .alignItems(HorizontalAlign.Start)
33
34        Row() {
35          Button() {
36            Text($r('app.string.JumpLabel'))
37              .fontColor('#45A6F4')
38              .fontSize(12)
39          }
40          .width(120)
41          .height(32)
42          .margin({ top: '30%', bottom: '10%' })
43          .backgroundColor('#FFFFFF')
44          .borderRadius(16)
45          .onClick(() => {
46            postCardAction(this, {
47              action: 'router',
48              abilityName: 'WidgetEventRouterEntryAbility', // 只能跳转到当前应用下的UIAbility
49              params: {
50                routerDetail: 'RouterFromCard',
51              }
52            });
53          })
54        }.width('100%').height('40%')
55        .justifyContent(FlexAlign.Center)
56      }
57      .width('100%')
58      .height('100%')
59      .alignItems(HorizontalAlign.Start)
60      .backgroundImage($r('app.media.CardEvent'))
61      .backgroundImageSize(ImageSize.Cover)
62    }
63  }
64  ```
65
66- 在UIAbility的onCreate或者onNewWant生命周期中可以通过入参want获取卡片的formID和传递过来的参数信息,然后调用[updateForm](../reference/apis-form-kit/js-apis-app-form-formProvider.md#updateform)接口刷新卡片。
67
68  ```ts
69  import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';
70  import { window } from '@kit.ArkUI';
71  import { BusinessError } from '@kit.BasicServicesKit';
72  import { formBindingData, formInfo, formProvider } from '@kit.FormKit';
73  import { hilog } from '@kit.PerformanceAnalysisKit';
74
75  const TAG: string = 'WidgetEventRouterEntryAbility';
76  const DOMAIN_NUMBER: number = 0xFF00;
77
78  export default class WidgetEventRouterEntryAbility extends UIAbility {
79    onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
80      this.handleFormRouterEvent(want, 'onCreate');
81    }
82
83    handleFormRouterEvent(want: Want, source: string): void {
84      hilog.info(DOMAIN_NUMBER, TAG, `handleFormRouterEvent ${source}, Want: ${JSON.stringify(want)}`);
85      if (want.parameters && want.parameters[formInfo.FormParam.IDENTITY_KEY] !== undefined) {
86        let curFormId = want.parameters[formInfo.FormParam.IDENTITY_KEY].toString();
87        // want.parameters.params 对应 postCardAction() 中 params 内容
88        let message: string = (JSON.parse(want.parameters?.params as string))?.routerDetail;
89        hilog.info(DOMAIN_NUMBER, TAG, `UpdateForm formId: ${curFormId}, message: ${message}`);
90        let formData: Record<string, string> = {
91          'routerDetail': message + ' ' + source + ' UIAbility', // 和卡片布局中对应
92        };
93        let formMsg = formBindingData.createFormBindingData(formData);
94        formProvider.updateForm(curFormId, formMsg).then((data) => {
95          hilog.info(DOMAIN_NUMBER, TAG, 'updateForm success.', JSON.stringify(data));
96        }).catch((error: BusinessError) => {
97          hilog.info(DOMAIN_NUMBER, TAG, 'updateForm failed.', JSON.stringify(error));
98        });
99      }
100    }
101
102    // 如果UIAbility已在后台运行,在收到Router事件后会触发onNewWant生命周期回调
103    onNewWant(want: Want, launchParam: AbilityConstant.LaunchParam): void {
104      hilog.info(DOMAIN_NUMBER, TAG, 'onNewWant Want:', JSON.stringify(want));
105      this.handleFormRouterEvent(want, 'onNewWant');
106    }
107
108    onWindowStageCreate(windowStage: window.WindowStage): void {
109
110      hilog.info(DOMAIN_NUMBER, TAG, '%{public}s', 'Ability onWindowStageCreate');
111
112      windowStage.loadContent('pages/Index', (err, data) => {
113        if (err.code) {
114          hilog.error(DOMAIN_NUMBER, TAG, 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
115          return;
116        }
117        hilog.info(DOMAIN_NUMBER, TAG, 'Succeeded in loading the content. Data: %{public}s', JSON.stringify(data) ?? '');
118      });
119    }
120    // ...
121  }
122  ```
123## 通过call事件刷新卡片内容
124
125- 在卡片页面代码文件中,通过注册Button的onClick点击事件回调并在回调中调用postCardAction接口,触发call事件拉起UIAbility至后台。
126
127  ```ts
128  let storageUpdateCall = new LocalStorage();
129
130  @Entry(storageUpdateCall)
131  @Component
132  struct WidgetUpdateCallCard {
133    @LocalStorageProp('formId') formId: string = '12400633174999288';
134    @LocalStorageProp('calleeDetail') calleeDetail: ResourceStr = $r('app.string.init');
135
136    build() {
137      Column() {
138        Column() {
139            Text(this.calleeDetail)
140            .fontColor('#FFFFFF')
141            .opacity(0.9)
142            .fontSize(14)
143            .margin({ top: '8%', left: '10%' })
144        }.width('100%').height('50%')
145        .alignItems(HorizontalAlign.Start)
146
147        Row() {
148          Button() {
149            Text($r('app.string.CalleeJumpLabel'))
150              .fontColor('#45A6F4')
151              .fontSize(12)
152          }
153          .width(120)
154          .height(32)
155          .margin({ top: '30%', bottom: '10%' })
156          .backgroundColor('#FFFFFF')
157          .borderRadius(16)
158          .onClick(() => {
159            postCardAction(this, {
160              action: 'call',
161              abilityName: 'WidgetCalleeEntryAbility', // 只能拉起当前应用下的UIAbility
162              params: {
163                method: 'funA',
164                formId: this.formId,
165                calleeDetail: 'CallFrom'
166              }
167            });
168          })
169        }.width('100%').height('40%')
170        .justifyContent(FlexAlign.Center)
171      }
172      .width('100%')
173      .height('100%')
174      .alignItems(HorizontalAlign.Start)
175      .backgroundImage($r('app.media.CardEvent'))
176      .backgroundImageSize(ImageSize.Cover)
177    }
178  }
179  ```
180
181- 在UIAbility的onCreate生命周期中监听call事件所需的方法,然后在对应方法中调用[updateForm](../reference/apis-form-kit/js-apis-app-form-formProvider.md#updateform)接口刷新卡片。
182
183  ```ts
184  import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';
185  import { window } from '@kit.ArkUI';
186  import { BusinessError } from '@kit.BasicServicesKit';
187  import { formBindingData, formProvider } from '@kit.FormKit';
188  import { rpc } from '@kit.IPCKit';
189  import { hilog } from '@kit.PerformanceAnalysisKit';
190
191  const TAG: string = 'WidgetCalleeEntryAbility';
192  const DOMAIN_NUMBER: number = 0xFF00;
193  const MSG_SEND_METHOD: string = 'funA';
194  const CONST_NUMBER_1: number = 1;
195
196  class MyParcelable implements rpc.Parcelable {
197    num: number;
198    str: string;
199
200    constructor(num: number, str: string) {
201      this.num = num;
202      this.str = str;
203    };
204
205    marshalling(messageSequence: rpc.MessageSequence): boolean {
206      messageSequence.writeInt(this.num);
207      messageSequence.writeString(this.str);
208      return true;
209    };
210
211    unmarshalling(messageSequence: rpc.MessageSequence): boolean {
212      this.num = messageSequence.readInt();
213      this.str = messageSequence.readString();
214      return true;
215    };
216  }
217
218  // 在收到call事件后会触发callee监听的方法
219  let funACall = (data: rpc.MessageSequence): MyParcelable => {
220    // 获取call事件中传递的所有参数
221    let params: Record<string, string> = JSON.parse(data.readString());
222    if (params.formId !== undefined) {
223      let curFormId: string = params.formId;
224      let message: string = params.calleeDetail;
225      hilog.info(DOMAIN_NUMBER, TAG, `UpdateForm formId: ${curFormId}, message: ${message}`);
226      let formData: Record<string, string> = {
227        'calleeDetail': message
228      };
229      let formMsg: formBindingData.FormBindingData = formBindingData.createFormBindingData(formData);
230      formProvider.updateForm(curFormId, formMsg).then((data) => {
231        hilog.info(DOMAIN_NUMBER, TAG, `updateForm success. ${JSON.stringify(data)}`);
232      }).catch((error: BusinessError) => {
233        hilog.error(DOMAIN_NUMBER, TAG, `updateForm failed: ${JSON.stringify(error)}`);
234      });
235    }
236    return new MyParcelable(CONST_NUMBER_1, 'aaa');
237  };
238
239  export default class WidgetCalleeEntryAbility extends UIAbility {
240    onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
241      try {
242        // 监听call事件所需的方法
243        this.callee.on(MSG_SEND_METHOD, funACall);
244      } catch (error) {
245        hilog.error(DOMAIN_NUMBER, TAG, `${MSG_SEND_METHOD} register failed with error ${JSON.stringify(error)}`);
246      }
247    }
248
249    onWindowStageCreate(windowStage: window.WindowStage): void {
250      // Main window is created, set main page for this ability
251      hilog.info(DOMAIN_NUMBER, TAG, '%{public}s', 'Ability onWindowStageCreate');
252
253      windowStage.loadContent('pages/Index', (err, data) => {
254        if (err.code) {
255          hilog.error(DOMAIN_NUMBER, TAG, 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
256          return;
257        }
258        hilog.info(DOMAIN_NUMBER, TAG, 'Succeeded in loading the content. Data: %{public}s', JSON.stringify(data) ?? '');
259      });
260    }
261  }
262  ```
263  要拉起UIAbility至后台,需要在`module.json5`配置文件中,配置`ohos.permission.KEEP_BACKGROUND_RUNNING`权限。
264  ```json
265    "requestPermissions":[
266        {
267        "name": "ohos.permission.KEEP_BACKGROUND_RUNNING"
268        }
269      ]
270  ```