写点什么

聚焦应用常用功能,提升用户体验与分发效率

作者:HarmonyOS SDK
  • 2025-03-28
    贵州
  • 本文字数:4889 字

    阅读完需:约 16 分钟

随着 HarmonyOS 应用的持续发展,应用的功能将越来越丰富,实际上 80%的用户使用时长都会集中在 20%的特性上,其余的功能可能也仅仅是面向部分用户。用户在下载应用时,如果应用包含大量的功能和资源,可能会导致下载时间过长;应用如果包含许多不常用或特定用户群体才需要的功能,这些功能会占用用户设备的存储空间;如果应用体积庞大,启动和运行速度可能会受到影响。


为了避免用户首次下载应用耗时过长,及过多占用用户空间,HarmonyOS SDK 应用市场服务(Store Kit)提供 产品特性按需分发的能力,能够提供动态分发和资源拆分,支持用户按需动态下载自己所需的增强特性,减少开发者应用的分发成本,将精力放在维护和分发用户实际需要的功能模块,帮助提高分发效率。

基本概念

按需分发:一个应用程序被打包成多个安装包,安装包包含了所有的应用程序代码和静态资源。用户从应用市场下载的应用只包含基本功能的安装包,当用户需要使用增强功能时,相应安装包将会从服务器下载到设备上。

开发步骤

获取模块安装信息

1.导入 moduleInstallManager 模块及相关公共模块。


import { moduleInstallManager } from '@kit.StoreKit';
复制代码


2.构造参数。


入参为需要查询的模块名称。


const moduleName: string = 'AModule';
复制代码


3.调用 getInstalledModule 方法,将步骤 2 中构造的参数传入模块中的 getInstalledModule 方法。


const moduleInfo: moduleInstallManager.InstalledModule = moduleInstallManager.getInstalledModule(moduleName);
复制代码

创建按需加载的请求实例

1.导入 moduleInstallManager 模块及相关公共模块。


import { moduleInstallManager } from '@kit.StoreKit';import type { common } from '@kit.AbilityKit';
复制代码


2.构造参数。


入参为当前应用的上下文 context,只支持 UIAbilityContext 和 ExtensionContext 类型的上下文,其中 UIAbilityContext 类型的上下文是要校验当前应用是否在前台,如果不在前台,则会被拒绝调用。


const context: common.UIAbilityContext | common.ExtensionContext = getContext(this) as common.UIAbilityContext;
复制代码


3.调用 createModuleInstallRequest 方法,将步骤 2 中构造的参数依次传入模块中的 createModuleInstallRequest 方法。


const myModuleInstallProvider: moduleInstallManager.ModuleInstallProvider = new moduleInstallManager.ModuleInstallProvider();const myModuleInstallRequest: moduleInstallManager.ModuleInstallRequest = myModuleInstallProvider.createModuleInstallRequest(context);
复制代码

请求按需加载的接口

1.导入 moduleInstallManager 模块及相关公共模块。


import type { common } from '@kit.AbilityKit';import { hilog } from '@kit.PerformanceAnalysisKit';import { moduleInstallManager } from '@kit.StoreKit';
复制代码


2.构造参数。


入参为当前要按需加载的模块名。


const moduleNameA: string = 'AModule';const moduleNameB: string = 'BModule';
复制代码


3.调用 ModuleInstallRequest 中的 addModule 方法,将步骤 2 中构造的参数依次传入模块中的 addModule 方法。


let myModuleInstallRequest: moduleInstallManager.ModuleInstallRequest;try {  const myModuleInstallProvider: moduleInstallManager.ModuleInstallProvider = new moduleInstallManager.ModuleInstallProvider();  const context: common.UIAbilityContext | common.ExtensionContext = getContext(this) as common.UIAbilityContext;  myModuleInstallRequest = myModuleInstallProvider.createModuleInstallRequest(context);  const aResult: moduleInstallManager.ReturnCode = myModuleInstallRequest.addModule(moduleNameA);  const bResult: moduleInstallManager.ReturnCode = myModuleInstallRequest.addModule(moduleNameB);  hilog.info(0, 'TAG', 'aResult:' + aResult + ' bResult:' + bResult);} catch (error) {  hilog.error(0, 'TAG', `addModule onError.code is ${error.code}, message is ${error.message}`);}
复制代码


4.调用 fetchModules 方法,将步骤三中的 myModuleInstallRequest 传入模块中的 fetchModules 方法。


try {  moduleInstallManager.fetchModules(myModuleInstallRequest)    .then((data: moduleInstallManager.ModuleInstallSessionState) => {      hilog.info(0, 'TAG', 'Succeeded in fetching Modules data.');    })} catch (error) {  hilog.error(0, 'TAG', `fetching Modules onError.code is ${error.code}, message is ${error.message}`);}
复制代码

使用动态模块

假如应用 A 由 entry.hap、AModulelib.hsp 两个包组成,其中 entry 是基础包,AModulelib 扩展是功能包(创建方式请参考应用程序包开发与使用)。通过应用市场下载安装只会下载安装 entry 包,在 entry 包里面可以通过 fetchModules 接口动态下载 AModulelib 包,并使用动态import技术调用 AModulelib 里的方法和组件。


AModulelib 中主要实现如下:


  • 在动态模块 AModulelib 中定义 add 方法和 DateComponent 组件。其中 add 方法用于计算加法,DateComponent 用于显示文本。


Calc.ets 定义如下:


export function add(a:number, b:number) {  return a + b;}
复制代码


DateComponent.ets 定义如下:


@Componentstruct DateComponent {  build() {    Column() {      Text('我是AModulelib中的组件')        .margin(10);    }    .width(300).backgroundColor(Color.Yellow);  }}

@Builderexport function showDateComponent() { DateComponent()}
复制代码


  • 在 AModulelib 的 AModulelib/Index.ets 中导出 add 方法和 showDateComponent 方法。


export { add } from './src/main/ets/utils/Calc';export { showDateComponent } from './src/main/ets/components/DateComponent';
复制代码


entry 中主要实现如下:


  • 在 entry 基础模块中,增加动态依赖配置。entry 的 oh-package.json5 中使用 dynamicDependencies 来动态依赖 AModulelib 模块。


{  "dynamicDependencies": {    "AModulelib": "file:../AModulelib"  }}
复制代码


  • 在 entry 中使用动态模块 AModulelib 模块里面的方法和组件。在调用 AModulelib 中的功能前需要判断 AModulelib 是否已经加载,未加载时请参考请求按需加载的接口完成加载。


import { moduleInstallManager } from '@kit.StoreKit';import { hilog } from '@kit.PerformanceAnalysisKit';import { BusinessError, Callback } from '@kit.BasicServicesKit';import { common } from '@kit.AbilityKit';import { promptAction } from '@kit.ArkUI';
const TAG: string = 'TAG';
@Entry@Componentstruct Index { @BuilderParam AModulelibComponent: Function; @State countTotal: number = 0; @State isShow: boolean = false;
build() { Row() { Column() { Button(`调用增量模块中的add功能:3+6`) .onClick(() => { this.initAModulelib(() => { import('AModulelib').then((ns: ESObject) => { this.countTotal = ns.add(3, 6); }).catch((error: BusinessError) => { hilog.error(0, 'TAG', `add onError.code is ${error.code}, message is ${error.message}`); }) }) }); Text('计算结果:' + this.countTotal) .margin(10); Button(`调用增量模块中的showDateComponent功能`) .onClick(() => { this.initAModulelib(() => { import('AModulelib').then((ns: ESObject) => { this.AModulelibComponent = ns.showDateComponent; this.isShow = true; }).catch((error: BusinessError) => { hilog.error(0, 'TAG', `showDateComponent onError.code is ${error.code}, message is ${error.message}`); }) }) }).margin({ top: 10, bottom: 10 }); if (this.isShow) { this.AModulelibComponent() } } .width('100%') } .height('100%') }
private showToastInfo(msg: string) { promptAction.showToast({ message: msg, duration: 2000 }); }
/** * 检查是否已加载AModulelib包 * * @param successCallBack 回调 */ private initAModulelib(successCallBack: Callback<void>): void { try { const result: moduleInstallManager.InstalledModule = moduleInstallManager.getInstalledModule('AModulelib'); if (result?.installStatus === moduleInstallManager.InstallStatus.INSTALLED) { hilog.info(0, TAG, 'AModulelib installed'); successCallBack &amp;&amp; successCallBack(); } else { // AModulelib模块未安装, 需要调用fetchModules下载AModulelib模块。 hilog.info(0, TAG, 'AModulelib not installed'); this.fetchModule('AModulelib', successCallBack) } } catch (error) { hilog.error(0, 'TAG', `getInstalledModule onError.code is ${error.code}, message is ${error.message}`); } }
/** * 添加监听事件 * * @param successCallBack 回调 */ private onListenEvents(successCallBack: Callback<void>): void { const timeout = 3 * 60; //单位秒, 默认最大监听时间为30min(即30*60秒) moduleInstallManager.on('moduleInstallStatus', (data: moduleInstallManager.ModuleInstallSessionState) =&gt; { // 返回成功 if (data.taskStatus === moduleInstallManager.TaskStatus.INSTALL_SUCCESSFUL) { successCallBack &amp;&amp; successCallBack(); this.showToastInfo('install success'); } }, timeout) }
/** * 加载指定包 * * @param moduleName 需要加载的安装包名称 * @param successCallBack 回调 */ private fetchModule(moduleName: string, successCallBack: Callback<void>) { try { hilog.info(0, TAG, 'handleFetchModules start'); const context = getContext(this) as common.UIAbilityContext; const moduleInstallProvider: moduleInstallManager.ModuleInstallProvider = new moduleInstallManager.ModuleInstallProvider(); const moduleInstallRequest: moduleInstallManager.ModuleInstallRequest = moduleInstallProvider.createModuleInstallRequest(context); if (!moduleInstallRequest) { hilog.warn(0, TAG, 'moduleInstallRequest is empty'); return; } moduleInstallRequest.addModule(moduleName); moduleInstallManager.fetchModules(moduleInstallRequest) .then((data: moduleInstallManager.ModuleInstallSessionState) =&gt; { hilog.info(0, TAG, 'Succeeded in fetching Modules result.'); if (data.code === moduleInstallManager.RequestErrorCode.SUCCESS) { this.onListenEvents(successCallBack) } else { hilog.info(0, TAG, 'fetchModules failure'); } }) .catch((error: BusinessError) =&gt; { hilog.error(0, 'TAG', `fetchModules onError.code is ${error.code}, message is ${error.message}`); }) } catch (error) { hilog.error(0, 'TAG', `handleFetchModules onError.code is ${error.code}, message is ${error.message}`); } }}
复制代码


了解更多详情>>


访问应用市场服务联盟官网


获取产品特性按需分发开发指导文档

用户头像

HarmonyOS SDK

关注

HarmonyOS SDK 2022-06-16 加入

HarmonyOS SDK通过将HarmonyOS系统级能力对外开放,支撑开发者高效打造更纯净、更智能、更精致、更易用的鸿蒙原生应用,和开发者共同成长。

评论

发布
暂无评论
聚焦应用常用功能,提升用户体验与分发效率_harmoyos_HarmonyOS SDK_InfoQ写作社区