欢迎光临
我们一直在努力

鸿蒙ArkTS卡片生命周期管理

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

在鸿蒙应用开发中,ArkTS卡片是一种轻量级的服务交互形态,可以在桌面上展示应用的核心信息和功能。而卡片生命周期管理则是控制卡片从创建到销毁整个过程的机制。

创建ArkTS卡片,必须实现FormExtensionAbility生命周期接口。FormExtensionAbility是卡片提供方(应用)用于处理卡片各种状态变化的入口点。

提示:

  • FormExtensionAbility进程不能常驻后台

  • 生命周期回调函数中无法处理长时间任务

  • 生命周期调度完成后会继续存在10秒

  • 10秒内无新回调触发则进程自动退出

二、基础配置与模块导入

2.1 导入相关模块

// entry/src/main/ets/entryformability/EntryFormAbility.ts

// FormKit模块 – 卡片相关核心功能
import { formBindingData, FormExtensionAbility, formInfo, formProvider } from '@kit.FormKit';

// AbilityKit模块 – 系统能力相关
import { Configuration, Want } from '@kit.AbilityKit';

// 基础服务模块 – 错误处理
import { BusinessError } from '@kit.BasicServicesKit';

// 性能分析模块 – 日志打印
import { hilog } from '@kit.PerformanceAnalysisKit';

模块说明:

模块主要功能用途
FormKit 卡片核心功能 卡片数据绑定、生命周期、更新等
AbilityKit 系统能力 配置信息、意图传递
BasicServicesKit 基础服务 错误类型定义
PerformanceAnalysisKit 性能分析 日志打印

三、FormExtensionAbility生命周期接口

3.1 生命周期方法

export default class EntryFormAbility extends FormExtensionAbility {
// 1. 添加卡片
onAddForm(want: Want): formBindingData.FormBindingData;

// 2. 更新卡片
onUpdateForm(formId: string): void;

// 3. 移除卡片
onRemoveForm(formId: string): void;

// 4. 卡片可见性变化
onChangeFormVisibility(newStatus: Record<string, number>): void;

// 5. 卡片事件
onFormEvent(formId: string, message: string): void;

// 6. 卡片状态查询
onAcquireFormState(want: Want): formInfo.FormState;

// 7. 配置更新
onConfigurationUpdate(config: Configuration): void;

// 8. 转换为普通卡片(当前无实际场景)
onCastToNormalForm(formId: string): void;
}

3.2 方法执行顺序图

卡片添加流程:
用户添加卡片 → onAddForm → 卡片显示

卡片更新流程:
定时/定点触发 → onUpdateForm → updateForm → 卡片刷新

卡片移除流程:
用户删除卡片 → onRemoveForm → 清理数据

卡片可见性变化:
划入屏幕 → onChangeFormVisibility(可见)
划出屏幕 → onChangeFormVisibility(不可见)

四、生命周期方法说明

4.1 onAddForm – 添加卡片

触发时机:卡片使用方(如桌面)创建卡片时触发

作用:卡片提供方需要返回卡片数据绑定类,用于初始化卡片显示内容

onAddForm(want: Want): formBindingData.FormBindingData {
hilog.info(0xFF00, 'EntryFormAbility', '[EntryFormAbility] onAddForm');

// 从want中获取卡片参数
const formName = want.parameters?.[formInfo.FormParam.NAME_KEY] as string;
hilog.info(0xFF00, 'EntryFormAbility', `formName: ${formName}`);

// 构建卡片数据
let obj: Record<string, string> = {
'title': 'titleOnAddForm', // 对应卡片UI中的变量
'detail': 'detailOnAddForm' // 对应卡片UI中的变量
};

// 创建卡片数据绑定对象
let formData: formBindingData.FormBindingData =
formBindingData.createFormBindingData(obj);

return formData;
}

参数说明:

参数类型说明
want Want 卡片创建时的意图信息,可通过FormParam取出卡片相关信息

Want中可获取的卡片参数(通过FormParam常量):

参数Key说明
formInfo.FormParam.NAME_KEY 卡片名称
formInfo.FormParam.DIMENSION_KEY 卡片规格(如2×2、2×4)
formInfo.FormParam.TEMPORARY_KEY 是否为临时卡片

返回值:formBindingData.FormBindingData – 卡片数据绑定对象

4.2 onUpdateForm – 更新卡片

触发时机:

  • 卡片配置了定时刷新(updateDuration)

  • 卡片配置了定点刷新(scheduledUpdateTime)

  • 卡片使用方主动请求更新

作用:提供数据更新,并调用updateForm刷新卡片显示

onUpdateForm(formId: string): void {
hilog.info(0xFF00, 'EntryFormAbility', '[EntryFormAbility] onUpdateForm');

// 构建更新数据
let obj: Record<string, string> = {
'title': 'titleOnUpdateForm', // 更新标题
'detail': 'detailOnUpdateForm' // 更新详情
};

// 创建卡片数据绑定对象
let formData: formBindingData.FormBindingData =
formBindingData.createFormBindingData(obj);

// 调用updateForm刷新卡片
formProvider.updateForm(formId, formData).catch((error: BusinessError) => {
hilog.info(0xFF00, 'EntryFormAbility',
'[EntryFormAbility] updateForm, error:' + JSON.stringify(error));
});
}

参数说明:

参数类型说明
formId string 要更新的卡片实例ID

重要方法:formProvider.updateForm(formId, formData)

  • 用于通知卡片框架更新指定卡片的数据

  • 返回Promise,需处理错误情况

4.3 onRemoveForm – 移除卡片

触发时机:卡片使用方删除卡片时触发

作用:清理卡片相关的持久化数据,释放资源

onRemoveForm(formId: string): void {
hilog.info(0xFF00, 'EntryFormAbility', '[EntryFormAbility] onRemoveForm');

// 删除之前持久化的卡片实例数据
// 示例:从本地数据库中删除该formId对应的数据
this.deletePersistentData(formId);

// 清理其他资源
this.releaseResources(formId);
}

private deletePersistentData(formId: string): void {
// 实际开发中实现具体的持久化数据删除逻辑
hilog.info(0xFF00, 'EntryFormAbility', `删除卡片 ${formId} 的持久化数据`);
}

private releaseResources(formId: string): void {
// 释放与卡片相关的资源
hilog.info(0xFF00, 'EntryFormAbility', `释放卡片 ${formId} 的资源`);
}

参数说明:

参数类型说明
formId string 被删除的卡片实例ID

4.4 onChangeFormVisibility – 可见性变化

触发时机:卡片使用方发起可见或者不可见通知时触发

作用:卡片提供方根据可见性做相应处理,如暂停/恢复动画、数据更新等

限制:仅系统应用生效

onChangeFormVisibility(newStatus: Record<string, number>): void {
hilog.info(0xFF00, 'EntryFormAbility', '[EntryFormAbility] onChangeFormVisibility');

// newStatus是一个字典,key为formId,value为可见性状态
for (let [formId, status] of Object.entries(newStatus)) {
if (status === 0) {
// 卡片变为不可见
hilog.info(0xFF00, 'EntryFormAbility', `卡片 ${formId} 变为不可见`);
this.pauseAnimation(formId);
} else {
// 卡片变为可见
hilog.info(0xFF00, 'EntryFormAbility', `卡片 ${formId} 变为可见`);
this.resumeAnimation(formId);
}
}
}

private pauseAnimation(formId: string): void {
// 暂停卡片中的动画
}

private resumeAnimation(formId: string): void {
// 恢复卡片中的动画
}

参数说明:

参数类型说明
newStatus Record<string, number> 键为卡片ID,值为可见性状态(0-不可见,1-可见)

4.5 onFormEvent – 卡片事件

触发时机:卡片支持触发事件时(如点击卡片中的按钮)

作用:处理卡片发送的事件,执行相应业务逻辑

onFormEvent(formId: string, message: string): void {
hilog.info(0xFF00, 'EntryFormAbility',
`FormAbility onFormEvent, formId = ${formId}, message: ${message}`);

// 解析事件消息
try {
const event = JSON.parse(message);

switch (event.type) {
case 'refresh':
this.handleRefreshEvent(formId, event.data);
break;
case 'navigate':
this.handleNavigateEvent(event.target);
break;
case 'action':
this.handleActionEvent(event.action, event.params);
break;
default:
hilog.warn(0xFF00, 'EntryFormAbility', `未知事件类型: ${event.type}`);
}
} catch (error) {
hilog.error(0xFF00, 'EntryFormAbility',
`事件解析失败: ${JSON.stringify(error)}`);
}
}

private handleRefreshEvent(formId: string, data: any): void {
// 处理刷新事件
// 可以更新卡片数据
const newData = formBindingData.createFormBindingData({
'title': '刷新后的标题',
'detail': '刷新后的详情'
});
formProvider.updateForm(formId, newData);
}

private handleNavigateEvent(target: string): void {
// 处理导航事件,拉起主应用
// 具体实现参考"拉起主应用"部分
}

private handleActionEvent(action: string, params: any): void {
// 处理自定义动作
hilog.info(0xFF00, 'EntryFormAbility', `执行动作: ${action}, 参数: ${JSON.stringify(params)}`);
}

参数说明:

参数类型说明
formId string 触发事件的卡片实例ID
message string 事件消息内容,通常为JSON字符串

4.6 onAcquireFormState – 卡片状态查询

触发时机:卡片提供方接收查询卡片状态通知时

作用:返回卡片当前状态,如是否准备好显示

onAcquireFormState(want: Want): formInfo.FormState {
hilog.info(0xFF00, 'EntryFormAbility', '[EntryFormAbility] onAcquireFormState');

// 可以根据want中的参数判断卡片状态
const formName = want.parameters?.[formInfo.FormParam.NAME_KEY] as string;

// 检查卡片是否可用
if (this.isFormAvailable(formName)) {
return formInfo.FormState.READY; // 卡片准备就绪
} else {
return formInfo.FormState.UNKNOWN; // 卡片不可用
}
}

private isFormAvailable(formName: string): boolean {
// 检查卡片是否可用
// 示例:检查配置、资源等
return true; // 默认返回true
}

返回值:formInfo.FormState枚举

状态值说明
FormState.READY 卡片已准备好,可以显示
FormState.UNKNOWN 卡片状态未知,不可用

4.7 onConfigurationUpdate – 配置更新

触发时机:FormExtensionAbility存活时,系统配置信息(如语言、主题)更新时触发

作用:响应系统配置变化,更新卡片内容

注意事项:FormExtensionAbility创建后10秒内无操作将会被清理

onConfigurationUpdate(config: Configuration): void {
hilog.info(0xFF00, 'EntryFormAbility',
'[EntryFormAbility] onConfigurationUpdate:' + JSON.stringify(config));

// 根据配置变化更新卡片
if (config.language) {
// 语言变化,更新多语言文本
this.updateFormTextByLanguage(config.language);
}

if (config.colorMode) {
// 主题变化,更新卡片主题
this.updateFormThemeByColorMode(config.colorMode);
}
}

private updateFormTextByLanguage(language: string): void {
// 根据新语言更新卡片文本
hilog.info(0xFF00, 'EntryFormAbility', `语言变更为: ${language}`);
// 实现具体的文本更新逻辑
}

private updateFormThemeByColorMode(colorMode: number): void {
// 根据新主题更新卡片样式
hilog.info(0xFF00, 'EntryFormAbility', `主题模式变更为: ${colorMode}`);
// 实现具体的主题更新逻辑
}

参数说明:

参数类型说明
config Configuration 系统配置信息,包含语言、颜色模式等

4.8 onCastToNormalForm – 转换为普通卡片

触发时机:当前卡片使用方不会涉及该场景

作用:无需实现该回调函数

onCastToNormalForm(formId: string): void {
// 当前卡片使用方不会涉及该场景,无需实现该回调函数
hilog.info(0xFF00, 'EntryFormAbility', '[EntryFormAbility] onCastToNormalForm');
// 此方法可以留空
}

五、注意事项

5.1 进程生命周期限制

// ⚠️ 重要:FormExtensionAbility进程生命周期
// 1. 生命周期回调执行完成后,进程会继续存在10秒
// 2. 10秒内无新的回调触发,进程自动退出
// 3. 无法在回调中执行长时间任务(>10秒)

// 正确示例:拉起主应用处理长时间任务
onFormEvent(formId: string, message: string): void {
if (message === 'doLongTask') {
// 拉起主应用处理
this.startMainAbility();
}
}

5.2 长时间任务处理策略

对于可能需要10秒以上才能完成的业务逻辑,建议:

  • 拉起主应用处理

  • 处理完成后使用updateForm通知卡片刷新

  • // 拉起主应用
    import { common, Want } from '@kit.AbilityKit';

    private async startMainAbility() {
    try {
    const context = this.context;
    const want: Want = {
    bundleName: 'com.example.myapp',
    abilityName: 'EntryAbility',
    parameters: {
    'action': 'updateForm'
    }
    };
    await context.startAbility(want);
    } catch (error) {
    hilog.error(DOMAIN_NUMBER, TAG,
    `拉起主应用失败: ${JSON.stringify(error)}`);
    }
    }

    5.3 卡片数据持久化

    // 卡片数据持久化示例(使用Preferences)
    import { preferences } from '@kit.ArkData';

    private async saveFormData(formId: string, data: Record<string, string>) {
    const prefs = await preferences.getPreferences(this.context, 'form_prefs');
    await prefs.put(formId, JSON.stringify(data));
    await prefs.flush();
    }

    private async getFormData(formId: string): Promise<Record<string, string> | null> {
    const prefs = await preferences.getPreferences(this.context, 'form_prefs');
    const jsonStr = await prefs.get(formId, '');
    return jsonStr ? JSON.parse(jsonStr) : null;
    }

    private async deleteFormData(formId: string) {
    const prefs = await preferences.getPreferences(this.context, 'form_prefs');
    await prefs.delete(formId);
    await prefs.flush();
    }

    六、完整生命周期实现

    // entry/src/main/ets/entryformability/EntryFormAbility.ts
    import { formBindingData, FormExtensionAbility, formInfo, formProvider } from '@kit.FormKit';
    import { Configuration, Want } from '@kit.AbilityKit';
    import { BusinessError } from '@kit.BasicServicesKit';
    import { hilog } from '@kit.PerformanceAnalysisKit';

    const TAG: string = 'EntryFormAbility';
    const DOMAIN_NUMBER: number = 0xFF00;

    export default class EntryFormAbility extends FormExtensionAbility {

    // 1. 添加卡片
    onAddForm(want: Want): formBindingData.FormBindingData {
    hilog.info(DOMAIN_NUMBER, TAG, '[EntryFormAbility] onAddForm');

    // 获取卡片参数
    const formName = want.parameters?.[formInfo.FormParam.NAME_KEY] as string;
    const dimension = want.parameters?.[formInfo.FormParam.DIMENSION_KEY] as number;
    hilog.info(DOMAIN_NUMBER, TAG, `formName: ${formName}, dimension: ${dimension}`);

    // 根据卡片规格返回不同的初始化数据
    let title = '';
    let detail = '';

    switch (dimension) {
    case 1: // 1×2
    title = '小号卡片';
    detail = '这是1×2规格的卡片';
    break;
    case 2: // 2×2
    title = '中号卡片';
    detail = '这是2×2规格的卡片';
    break;
    case 3: // 2×4
    title = '大号卡片';
    detail = '这是2×4规格的卡片';
    break;
    default:
    title = '默认卡片';
    detail = '这是默认规格的卡片';
    }

    // 构建卡片数据
    let obj: Record<string, string> = {
    'title': title,
    'detail': detail,
    'timestamp': new Date().toLocaleString()
    };

    // 持久化卡片数据(可选)
    this.saveFormData(want, obj);

    // 创建卡片数据绑定对象
    return formBindingData.createFormBindingData(obj);
    }

    // 2. 更新卡片
    onUpdateForm(formId: string): void {
    hilog.info(DOMAIN_NUMBER, TAG, '[EntryFormAbility] onUpdateForm');

    // 构建更新数据
    let obj: Record<string, string> = {
    'title': '定时更新标题',
    'detail': `更新于 ${new Date().toLocaleString()}`,
    'timestamp': new Date().toLocaleString()
    };

    // 创建卡片数据绑定对象
    let formData: formBindingData.FormBindingData =
    formBindingData.createFormBindingData(obj);

    // 更新卡片
    formProvider.updateForm(formId, formData).catch((error: BusinessError) => {
    hilog.info(DOMAIN_NUMBER, TAG,
    '[EntryFormAbility] updateForm, error:' + JSON.stringify(error));
    });
    }

    // 3. 移除卡片
    onRemoveForm(formId: string): void {
    hilog.info(DOMAIN_NUMBER, TAG, '[EntryFormAbility] onRemoveForm');

    // 删除持久化的卡片数据
    this.deleteFormData(formId);
    }

    // 4. 可见性变化
    onChangeFormVisibility(newStatus: Record<string, number>): void {
    hilog.info(DOMAIN_NUMBER, TAG, '[EntryFormAbility] onChangeFormVisibility');

    for (let [formId, status] of Object.entries(newStatus)) {
    hilog.info(DOMAIN_NUMBER, TAG,
    `卡片 ${formId} 可见性变更为: ${status === 1 ? '可见' : '不可见'}`);

    if (status === 1) {
    // 变为可见时,可以刷新数据
    this.refreshFormIfNeeded(formId);
    }
    }
    }

    // 5. 卡片事件
    onFormEvent(formId: string, message: string): void {
    hilog.info(DOMAIN_NUMBER, TAG,
    `FormAbility onFormEvent, formId = ${formId}, message: ${message}`);

    try {
    const event = JSON.parse(message);

    if (event.action === 'refresh') {
    // 手动刷新
    this.handleManualRefresh(formId);
    } else if (event.action === 'openApp') {
    // 打开主应用
    this.openMainApp();
    }
    } catch (error) {
    hilog.error(DOMAIN_NUMBER, TAG,
    `事件处理失败: ${JSON.stringify(error)}`);
    }
    }

    // 6. 卡片状态查询
    onAcquireFormState(want: Want): formInfo.FormState {
    hilog.info(DOMAIN_NUMBER, TAG, '[EntryFormAbility] onAcquireFormState');
    return formInfo.FormState.READY;
    }

    // 7. 配置更新
    onConfigurationUpdate(config: Configuration) {
    hilog.info(DOMAIN_NUMBER, TAG,
    '[EntryFormAbility] onConfigurationUpdate:' + JSON.stringify(config));
    }

    // 8. 转换为普通卡片(留空)
    onCastToNormalForm(formId: string): void {
    hilog.info(DOMAIN_NUMBER, TAG, '[EntryFormAbility] onCastToNormalForm');
    }

    // ============== 私有辅助方法 ==============

    private saveFormData(want: Want, data: Record<string, string>): void {
    // 实现卡片数据的持久化
    // 可以使用Preferences、数据库等
    hilog.info(DOMAIN_NUMBER, TAG, '保存卡片数据');
    }

    private deleteFormData(formId: string): void {
    // 删除持久化的卡片数据
    hilog.info(DOMAIN_NUMBER, TAG, `删除卡片 ${formId} 的数据`);
    }

    private refreshFormIfNeeded(formId: string): void {
    // 根据需要刷新卡片
    hilog.info(DOMAIN_NUMBER, TAG, `刷新卡片 ${formId}`);
    }

    private handleManualRefresh(formId: string): void {
    // 处理手动刷新事件
    const newData = formBindingData.createFormBindingData({
    'title': '手动刷新',
    'detail': `刷新于 ${new Date().toLocaleString()}`
    });

    formProvider.updateForm(formId, newData).catch((error: BusinessError) => {
    hilog.error(DOMAIN_NUMBER, TAG,
    `手动刷新失败: ${JSON.stringify(error)}`);
    });
    }

    private openMainApp(): void {
    // 拉起主应用
    // 具体实现参考"拉起主应用"部分
    hilog.info(DOMAIN_NUMBER, TAG, '拉起主应用');
    }
    }

    赞(0)
    未经允许不得转载:171主机测评 » 鸿蒙ArkTS卡片生命周期管理
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址