# 如何在卡片上刷新展示多张图片

#### 问题现象

卡片加载时，有多张图片需要显示在卡片页面里，如何一次性添加到卡片页面上？

#### 背景知识

*   formBindingData.createFormBindingData：创建一个FormBindingData对象。参数中图片数据以'formImages'作为标识，内容为图片标识与图片文件描述符的键值对{'formImages': {'key1': fd1, 'key2': fd2}}。
*   fs.listFileSync：默认以同步方式列出当前目录下所有文件名和目录名。支持过滤。可通过配置options中recursion参数实现递归列出所有文件的相对路径，相对路径以“/”开头。

#### 解决方案

以将沙箱filesDir目录下图片添加到卡片页面为例：

1.  在卡片生命周期onAddForm中获取沙箱filesDir目录下的图片，构造传递给卡片页面的数据。
    
    ```
    import { formBindingData, FormExtensionAbility } from '@kit.FormKit';
    import { Want } from '@kit.AbilityKit';
    import { fileIo as fs, ListFileOptions } from '@kit.CoreFileKit';
    
    
    export default class EntryFormAbility extends FormExtensionAbility {
      onAddForm(want: Want) {
        let formId = "";
        let parameters = want.parameters;
        if (parameters) {
          formId = parameters["ohos.extra.param.key.form_identity"] as string;
          console.info("onAddForm formId ", formId);
        }
        // 遍历出沙箱路径下的图片（保证对应沙箱路径下有相应格式图片）
        let dir: string = this.context.filesDir;
        let listFileOption: ListFileOptions = {
          recursion: false,
          listNum: 0,
          filter: {
            suffix: [".png", ".jpg", ".jpeg"]
          }
        };
        let filenames = fs.listFileSync(dir, listFileOption);
        console.info("filenames: ", JSON.stringify(filenames));
        let imgMap: Record<string, number> = {};
        for (let i = 0; i < filenames.length; i++) {
          // 打开本地图片并获取其打开后的fd
          let file = fs.openSync(dir + '/' + filenames[i]);
          imgMap[filenames[i]] = file.fd;
        }
    
    
        class FormDataClass {
          formId: string = formId;
          // 卡片需要显示图片场景, 必须和formImages中的key对应
          imgNames: string[] = filenames;
          // 卡片需要显示图片场景, 必填字段(formImages不可缺省或改名)
          formImages: Record<string, number> = imgMap;
        }
    
    
        let formData = new FormDataClass();
        return formBindingData.createFormBindingData(formData);
      }
    }
    ```
    
2.  卡片页面接收数据并展示图片。
    
    ```
    let storageWidgetImageUpdate = new LocalStorage();
    
    
    @Entry(storageWidgetImageUpdate)
    @Component
    export struct WidgetCard {
      @LocalStorageProp('formId') formId: string = "";
      @LocalStorageProp('imgNames') imgNames: string[] = [];
    
    
      build() {
        List({ space: 10 }) {
          ForEach(this.imgNames, (item: string) => {
            ListItem() {
              Row() {
                Text(item + ": ")
                  .layoutWeight(1)
                  .height(20)
                  .fontSize(12)
                  .textAlign(TextAlign.Start)
                Image('memory://' + item)
                  .height(20)
                  .width(20)
                  .objectFit(ImageFit.Contain)
              }
              .justifyContent(FlexAlign.Start)
            }
            .id(item)
            .width('100%')
          })
        }
        .listDirection(Axis.Vertical)
        .width('100%')
        .height('100%')
        .padding(10)
      }
    }
    ```
    
    效果如下：
    

#### 常见FAQ

Q：服务卡片中是否可以加载GIF图？

A：服务卡片可使用Image组件直接加载GIF图。为避免卡片频繁渲染刷新带来的功耗问题，GIF图只能播放一次，因此不建议通过服务卡片实现高频的动态变换界面效果。对于前期突破该规则的应用，近期将进行整改。

#### 总结

formBindingData.createFormBindingData(formData)构造传递给卡片页面的数据时通过formImages字段会将图片fd保存在内存中，卡片页面接收formImages里的key值即可通过key找到图片展示在图片组件。多图片场景时需要保证每张图片的key都是唯一的。