1# 刷新本地图片和网络图片
2
3
4在卡片上通常需要展示本地图片或从网络上下载的图片,获取本地图片和网络图片需要通过FormExtensionAbility来实现,如下示例代码介绍了如何在卡片上显示本地图片和网络图片。
5
6
71. 下载网络图片需要使用到网络能力,需要申请ohos.permission.INTERNET权限,配置方式请参见[声明权限](../security/AccessToken/declare-permissions.md)。
8
92. 在EntryFormAbility中的onAddForm生命周期回调中实现本地文件的刷新。
10
11    ```ts
12    import { Want } from '@kit.AbilityKit';
13    import { BusinessError } from '@kit.BasicServicesKit';
14    import { fileIo } from '@kit.CoreFileKit';
15    import { formBindingData, FormExtensionAbility } from '@kit.FormKit';
16    import { hilog } from '@kit.PerformanceAnalysisKit';
17
18    const TAG: string = 'WgtImgUpdateEntryFormAbility';
19    const DOMAIN_NUMBER: number = 0xFF00;
20
21    export default class WgtImgUpdateEntryFormAbility extends FormExtensionAbility {
22      // 在添加卡片时,打开一个本地图片并将图片内容传递给卡片页面显示
23      onAddForm(want: Want): formBindingData.FormBindingData {
24        // 假设在当前卡片应用的tmp目录下有一个本地图片:head.PNG
25        let tempDir = this.context.getApplicationContext().tempDir;
26        hilog.info(DOMAIN_NUMBER, TAG, `tempDir: ${tempDir}`);
27        let imgMap: Record<string, number> = {};
28        try {
29          // 打开本地图片并获取其打开后的fd
30          let file = fileIo.openSync(tempDir + '/' + 'head.PNG');
31          imgMap['imgBear'] = file.fd;
32        } catch (e) {
33          hilog.error(DOMAIN_NUMBER, TAG, `openSync failed: ${JSON.stringify(e as BusinessError)}`);
34        }
35
36        class FormDataClass {
37          text: string = 'Image: Bear';
38          loaded: boolean = true;
39          // 卡片需要显示图片场景, 必须和下列字段formImages 中的key 'imgBear' 相同。
40          imgName: string = 'imgBear';
41          // 卡片需要显示图片场景, 必填字段(formImages 不可缺省或改名), 'imgBear' 对应 fd
42          formImages: Record<string, number> = imgMap;
43        }
44
45        let formData = new FormDataClass();
46        // 将fd封装在formData中并返回至卡片页面
47        return formBindingData.createFormBindingData(formData);
48      }
49      //...
50    }
51    ```
52
533. 在EntryFormAbility中的onFormEvent生命周期回调中实现网络文件的刷新。
54
55      ```ts
56      import { BusinessError } from '@kit.BasicServicesKit';
57      import { fileIo } from '@kit.CoreFileKit';
58      import { formBindingData, FormExtensionAbility, formProvider } from '@kit.FormKit';
59      import { http } from '@kit.NetworkKit';
60      import { hilog } from '@kit.PerformanceAnalysisKit';
61
62      const TAG: string = 'WgtImgUpdateEntryFormAbility';
63      const DOMAIN_NUMBER: number = 0xFF00;
64
65      export default class WgtImgUpdateEntryFormAbility extends FormExtensionAbility {
66        async onFormEvent(formId: string, message: string): Promise<void> {
67          let param: Record<string, string> = {
68            'text': '刷新中...'
69          };
70          let formInfo: formBindingData.FormBindingData = formBindingData.createFormBindingData(param);
71          formProvider.updateForm(formId, formInfo);
72
73          // 注意:FormExtensionAbility在触发生命周期回调时被拉起,仅能在后台存在5秒
74          // 建议下载能快速下载完成的小文件,如在5秒内未下载完成,则此次网络图片无法刷新至卡片页面上
75          let netFile = 'https://cn-assets.gitee.com/assets/mini_app-e5eee5a21c552b69ae6bf2cf87406b59.jpg'; // 需要在此处使用真实的网络图片下载链接
76          let tempDir = this.context.getApplicationContext().tempDir;
77          let fileName = 'file' + Date.now();
78          let tmpFile = tempDir + '/' + fileName;
79          let imgMap: Record<string, number> = {};
80
81          class FormDataClass {
82            text: string = 'Image: Bear' + fileName;
83            loaded: boolean = true;
84            // 卡片需要显示图片场景, 必须和下列字段formImages 中的key fileName 相同。
85            imgName: string = fileName;
86            // 卡片需要显示图片场景, 必填字段(formImages 不可缺省或改名), fileName 对应 fd
87            formImages: Record<string, number> = imgMap;
88          }
89
90          let httpRequest = http.createHttp()
91          let data = await httpRequest.request(netFile);
92          if (data?.responseCode == http.ResponseCode.OK) {
93            try {
94              let imgFile = fileIo.openSync(tmpFile, fileIo.OpenMode.READ_WRITE | fileIo.OpenMode.CREATE);
95              imgMap[fileName] = imgFile.fd;
96              try{
97                let writeLen: number = await fileIo.write(imgFile.fd, data.result as ArrayBuffer);
98                hilog.info(DOMAIN_NUMBER, TAG, "write data to file succeed and size is:" + writeLen);
99                hilog.info(DOMAIN_NUMBER, TAG, 'ArkTSCard download complete: %{public}s', tmpFile);
100                try {
101                  let formData = new FormDataClass();
102                  let formInfo = formBindingData.createFormBindingData(formData);
103                  await formProvider.updateForm(formId, formInfo);
104                  hilog.info(DOMAIN_NUMBER, TAG, '%{public}s', 'FormAbility updateForm success.');
105                } catch (error) {
106                  hilog.error(DOMAIN_NUMBER, TAG, `FormAbility updateForm failed: ${JSON.stringify(error)}`);
107                }
108              } catch (err) {
109                hilog.error(DOMAIN_NUMBER, TAG, "write data to file failed with error message: " + err.message + ", error code: " + err.code);
110              } finally {
111                fileIo.closeSync(imgFile);
112              };
113            } catch (e) {
114              hilog.error(DOMAIN_NUMBER, TAG, `openSync failed: ${JSON.stringify(e as BusinessError)}`);
115            }
116
117          } else {
118            hilog.error(DOMAIN_NUMBER, TAG, `ArkTSCard download task failed`);
119            let param: Record<string, string> = {
120              'text': '刷新失败'
121            };
122            let formInfo: formBindingData.FormBindingData = formBindingData.createFormBindingData(param);
123            formProvider.updateForm(formId, formInfo);
124          }
125          httpRequest.destroy();
126        }
127      }
128      ```
129
1304. 在卡片页面通过backgroundImage属性展示EntryFormAbility传递过来的卡片内容。
131
132    ```ts
133    let storageWidgetImageUpdate = new LocalStorage();
134
135    @Entry(storageWidgetImageUpdate)
136    @Component
137    struct WidgetImageUpdateCard {
138      @LocalStorageProp('text') text: ResourceStr = $r('app.string.loading');
139      @LocalStorageProp('loaded') loaded: boolean = false;
140      @LocalStorageProp('imgName') imgName: ResourceStr = $r('app.string.imgName');
141
142      build() {
143        Column() {
144          Column() {
145            Text(this.text)
146              .fontColor('#FFFFFF')
147              .opacity(0.9)
148              .fontSize(12)
149              .textOverflow({ overflow: TextOverflow.Ellipsis })
150              .maxLines(1)
151              .margin({ top: '8%', left: '10%' })
152          }.width('100%').height('50%')
153          .alignItems(HorizontalAlign.Start)
154
155          Row() {
156            Button() {
157              Text($r('app.string.update'))
158                .fontColor('#45A6F4')
159                .fontSize(12)
160            }
161            .width(120)
162            .height(32)
163            .margin({ top: '30%', bottom: '10%' })
164            .backgroundColor('#FFFFFF')
165            .borderRadius(16)
166            .onClick(() => {
167              postCardAction(this, {
168                action: 'message',
169                params: {
170                  info: 'refreshImage'
171                }
172              });
173            })
174          }.width('100%').height('40%')
175          .justifyContent(FlexAlign.Center)
176        }
177        .width('100%').height('100%')
178        .backgroundImage(this.loaded ? 'memory://' + this.imgName : $r('app.media.ImageDisp'))
179        .backgroundImageSize(ImageSize.Cover)
180      }
181    }
182    ```
183
184> **说明:**
185>
186> - Image组件通过入参(memory://fileName)中的(memory://)标识来进行远端内存图片显示,其中fileName需要和EntryFormAbility传递对象('formImages': {key: fd})中的key相对应。
187>
188> - Image组件通过传入的参数是否有变化来决定是否刷新图片,因此EntryFormAbility每次传递过来的imgName都需要不同,连续传递两个相同的imgName时,图片不会刷新。
189>
190> - 在卡片上展示的图片,大小需要控制在2MB以内。
191