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