鸿蒙开发中FormProvider模块的全面解析

本文同步发表于我的微信公众号,微信搜索 程语新视界 即可关注,每个工作日都有文章更新

FormProvider是鸿蒙(HarmonyOS)开发中用于卡片(Form)管理的核心模块,提供了卡片更新、定时刷新、信息获取等关键功能。本文将深入讲解FormProvider的使用方法、常用API及实际应用场景。

一、FormProvider模块概述

FormProvider模块是鸿蒙卡片开发的核心接口,主要功能包括:

  • 更新卡片内容数据
  • 设置卡片下一次更新时间
  • 获取卡片信息
  • 请求发布卡片等

模块导入方式

import formProvider from '@ohos.application.formProvider';

系统能力:SystemCapability.Ability.Form

版本说明

  • 首批接口从API version 8开始支持
  • API version 9开始建议使用formProvider替代原有接口 

二、核心API详解

1. 设置卡片刷新时间(setFormNextRefreshTime)

设置卡片下一次自动更新的时间间隔,支持两种调用方式:

Callback方式
setFormNextRefreshTime(formId: string, minute: number, callback: AsyncCallback): void

参数说明

  • formId: 卡片标识,字符串类型,必填
  • minute: 刷新间隔时间(分钟),必须≥5,数字类型,必填
  • callback: 异步回调函数,返回操作结果

示例代码

let formId = "12400633174999288";
formProvider.setFormNextRefreshTime(formId, 5, (error) => {
  if (error.code) {
    console.error(`设置失败: ${JSON.stringify(error)}`);
  } else {
    console.log("设置成功");
  }
});

Promise方式 

setFormNextRefreshTime(formId: string, minute: number): Promise

示例代码

let formId = "12400633174999288";
formProvider.setFormNextRefreshTime(formId, 5)
  .then(() => {
    console.log("设置成功");
  })
  .catch((error) => {
    console.error(`设置失败: ${JSON.stringify(error)}`);
  });

注意事项

  • 最小刷新间隔为5分钟
  • 卡片刷新时会重新调用onCreateForm生命周期 

2. 更新卡片内容(updateForm)

更新指定卡片的内容数据,同样支持两种调用方式:

Callback方式
updateForm(formId: string, formBindingData: FormBindingData, callback: AsyncCallback): void

参数说明

  • formId: 要更新的卡片标识
  • formBindingData: 绑定数据对象,使用formBindingData模块创建
  • callback: 异步回调函数

示例代码

import formBindingData from '@ohos.application.formBindingData';

let formId = "12400633174999288";
let data = {
  temperature: "22℃",
  time: "22:00"
};
let bindingData = formBindingData.createFormBindingData(data);

formProvider.updateForm(formId, bindingData, (error) => {
  if (error.code) {
    console.error(`更新失败: ${JSON.stringify(error)}`);
  }
});
Promise方式
updateForm(formId: string, formBindingData: FormBindingData): Promise

示例代码

formProvider.updateForm(formId, bindingData)
  .then(() => {
    console.log("更新成功");
  })
  .catch((error) => {
    console.error(`更新失败: ${JSON.stringify(error)}`);
  });

数据绑定说明

  • 使用formBindingData.createFormBindingData()创建绑定数据
  • 支持传递复杂对象,但卡片端需有对应解析逻辑 

3. 获取卡片信息(getFormsInfo)

获取当前应用已创建的卡片信息:

getFormsInfo(callback: AsyncCallback>): void
getFormsInfo(): Promise>

返回数据格式

interface FormInfo {
  formId: string;          // 卡片ID
  packageName: string;     // 包名
  bundleName: string;      // 应用Bundle名称
  abilityName: string;     // Ability名称
  moduleName: string;      // 模块名称
  formName: string;        // 卡片名称
  formConfigAbility: string; // 配置Ability
  formVisible: boolean;    // 是否可见
  formUpdated: boolean;    // 是否已更新
  updateEnabled: boolean;  // 是否启用更新
  defaultFlag: boolean;    // 是否默认卡片
  supportDimensions: Array; // 支持的尺寸
  defaultDimension: number; // 默认尺寸
}

示例代码

// callback方式
formProvider.getFormsInfo((error, data) => {
  if (!error.code) {
    data.forEach(info => {
      console.log(`卡片ID: ${info.formId}, 名称: ${info.formName}`);
    });
  }
});

// promise方式
formProvider.getFormsInfo()
  .then(data => {
    // 处理卡片信息
  })
  .catch(error => {
    console.error(error);
  });

三、完整卡片开发流程

1. 卡片配置

resources/base/profile/form_config.json中配置卡片信息:

{
  "forms": [{
    "name": "widget",
    "description": "This is a weather widget.",
    "src": "./js/widget/index",
    "window": {
      "designWidth": 720,
      "autoDesignWidth": true
    },
    "colorMode": "auto",
    "isDefault": true,
    "updateEnabled": true,
    "defaultDimension": "2*2",
    "supportDimensions": ["2*2", "2*4"]
  }]
}

2. 卡片Ability开发

创建FormAbility.ts处理卡片生命周期:

import formBindingData from '@ohos.application.formBindingData';
import formProvider from '@ohos.application.formProvider';

export default class FormAbility {
  onCreateForm(want) {
    console.log("FormAbility onCreateForm");
    let formData = {
      title: "天气获取卡片",
      temperature: "22℃",
      location: "北京"
    };
    return formBindingData.createFormBindingData(formData);
  }

  onCastToNormalForm(formId) {
    // 卡片转为常态回调
  }

  onUpdateForm(formId) {
    // 卡片更新回调
    let newData = {
      title: "天气获取卡片(更新)",
      temperature: "24℃",
      location: "北京"
    };
    formProvider.updateForm(formId, formBindingData.createFormBindingData(newData))
      .catch(error => {
        console.error(`更新失败: ${JSON.stringify(error)}`);
      });
  }

  onRemoveForm(formId) {
    // 卡片删除回调
  }
}

3. 卡片UI开发

@Entry
@Component
struct WeatherCard {
  @State temperature: string = "22℃"

  build() {
    Column() {
      Text("当前温度")
        .fontSize(16)
      Text(this.temperature)
        .fontSize(24)
        .margin({ top: 8 })
    }
    .padding(12)
    .backgroundColor("#F5F5F5")
  }
}

四、高级功能

1. 定时刷新与数据更新结合

// 设置每10分钟刷新一次,并在刷新时更新数据
function setupFormRefresh(formId: string) {
  formProvider.setFormNextRefreshTime(formId, 10)
    .then(() => {
      // 立即更新一次数据
      updateFormData(formId);
    });
}

function updateFormData(formId: string) {
  fetchWeatherData().then(data => {
    let bindingData = formBindingData.createFormBindingData(data);
    return formProvider.updateForm(formId, bindingData);
  }).catch(error => {
    console.error("数据更新失败", error);
  });
}

2. 多卡片管理

// 获取所有卡片并批量更新
formProvider.getFormsInfo()
  .then(forms => {
    forms.forEach(form => {
      if (form.formName === "weather_widget") {
        updateWeatherForm(form.formId);
      }
    });
  });

function updateWeatherForm(formId: string) {
  // 特定卡片的更新逻辑
}

3. 错误处理与日志

function safeUpdateForm(formId: string, data: object) {
  try {
    let bindingData = formBindingData.createFormBindingData(data);
    formProvider.updateForm(formId, bindingData)
      .then(() => {
        console.log("更新成功");
      })
      .catch(error => {
        logError("UPDATE_FORM_ERROR", error, { formId });
      });
  } catch (e) {
    logError("CREATE_BINDING_ERROR", e, { formId });
  }
}

function logError(type: string, error: any, meta: object) {
  console.error(JSON.stringify({
    type,
    time: new Date().toISOString(),
    error: {
      code: error.code || -1,
      message: error.message || "Unknown error"
    },
    meta
  }));
}

五、常见问题与解决方案

1. 卡片更新不生效

  • 检查点1:确认formId是否正确
  • 检查点2:验证formBindingData是否创建成功
  • 检查点3:检查卡片配置中updateEnabled是否为true

2. 定时刷新无效

  • 原因:可能设置了小于5分钟的间隔
  • 解决方案:确保minute参数≥5 

3. 数据绑定异常

  • 最佳实践:使用简单数据结构,复杂对象需双方约定格式
  • 调试技巧:先使用固定数据测试卡片UI渲染

4. 多卡片数据隔离

  • 解决方案:根据formId区分不同卡片的数据源
  • 示例
const formDataMap = new Map();

function getFormData(formId: string) {
  if (!formDataMap.has(formId)) {
    formDataMap.set(formId, fetchInitialData());
  }
  return formDataMap.get(formId);
}

六、实际应用案例:天气卡片

1. 数据模型定义

interface WeatherData {
  city: string;
  temperature: string;
  weather: string;
  humidity: string;
  wind: string;
  updateTime: string;
}

2. 完整卡片Ability

export default class WeatherFormAbility {
  private formData: Map = new Map();
  
  onCreateForm(want) {
    let formId = want.parameters["ohos.extra.param.key.form_identity"];
    let city = want.parameters["city"] || "北京";
    
    return this.fetchWeather(formId, city);
  }

  private async fetchWeather(formId: string, city: string) {
    try {
      let data = await weatherService.get(city);
      this.formData.set(formId, data);
      return formBindingData.createFormBindingData(data);
    } catch (error) {
      console.error("获取天气失败", error);
      return formBindingData.createFormBindingData({
        city,
        temperature: "--",
        weather: "获取失败",
        updateTime: new Date().toLocaleTimeString()
      });
    }
  }

  onUpdateForm(formId) {
    if (this.formData.has(formId)) {
      let data = this.formData.get(formId);
      this.fetchWeather(formId, data.city);
      
      // 设置下次刷新(30分钟)
      formProvider.setFormNextRefreshTime(formId, 30);
    }
  }
}

3. 卡片UI增强

// WeatherCard.ets
@Entry
@Component
struct WeatherCard {
  @State temperature: string = "22℃"
  @State city: string = "北京"
  @State weatherIcon: Resource = $r('app.media.sunny')

  build() {
    Column() {
      // 城市名称
      Text(this.city)
        .fontSize(18)
        .fontColor('#333')
      
      // 温度与图标
      Row() {
        Text(this.temperature)
          .fontSize(36)
        Image(this.weatherIcon)
          .width(40)
          .height(40)
      }
      .margin({ top: 8 })

      // 更新时间
      Text(`更新: ${new Date().toLocaleTimeString()}`)
        .fontSize(12)
        .fontColor('#666')
    }
    .padding(16)
    .backgroundColor('#FFFFFF')
    .borderRadius(12)
    .onClick(() => {
      // 点击刷新数据
      this.updateWeather()
    })
  }

  // 更新天气数据
  private updateWeather() {
    // 模拟数据更新
    this.temperature = `${Math.floor(18 + Math.random() * 10)}℃`
  }
}

你可能感兴趣的:(鸿蒙,harmonyos,华为,鸿蒙,卡片)