鸿蒙HarmonyOS开发往期必看:
HarmonyOS NEXT应用开发性能实践总结
最新版!“非常详细的” 鸿蒙HarmonyOS Next应用开发学习路线!(从零基础入门到精通)
介绍
本示例将介绍如何使用装饰器和插件,自动生成动态路由表,并通过动态路由跳转到模块中的页面,以及如何使用动态import的方式加载模块。
目前,已有三方库HMRouter封装了完整的动态路由功能,添加了生命周期回调、内置转场动画等功能,如有需要,可直接使用。
使用说明
- 自定义装饰器
- 添加装饰器和插件配置文件,编译时自动生成动态路由表
- 配置动态路由,通过WrapBuilder接口,动态创建页面并跳转。
- 动态import变量表达式,需要DevEco Studio NEXT Developer Preview1 (4.1.3.500)版本IDE,配合hvigor 4.0.2版本使用。
- 支持自定义路由栈管理
实现思路
动态路由的实现
-
初始化动态路由
public static routerInit(config: RouterConfig, context: Context) {DynamicsRouter.config = config;DynamicsRouter.appRouterStack.push(HOME_PAGE);RouterLoader.load(config.mapPath, DynamicsRouter.routerMap, context);}
-
获取路由
private static getNavPathStack(): NavPathStack {return DynamicsRouter.navPathStack; }
-
通过builderName,注册WrappedBuilder对象,用于动态创建页面
private static registerBuilder(builderName: string, builder: WrappedBuilder<[object]>): void {DynamicsRouter.builderMap.set(builderName, builder); }
-
通过builderName,获取注册的WrappedBuilder对象
public static getBuilder(builderName: string): WrappedBuilder<[object]> {let builder = DynamicsRouter.builderMap.get(builderName);if (!builder) {let msg = "not found builder";console.info(msg + builderName);}return builder as WrappedBuilder<[object]>; }
-
通过页面栈跳转到指定页面
public static pushUri(name: string, param?: Object) {if (!DynamicsRouter.routerMap.has(name)) {return;}let routerInfo: AppRouterInfo = DynamicsRouter.routerMap.get(name)!;if (!DynamicsRouter.builderMap.has(name)) {import(`${DynamicsRouter.config.libPrefix}/${routerInfo.pageModule}`).then((module: ESObject) => {module[routerInfo.registerFunction!](routerInfo);DynamicsRouter.navPathStack.pushPath({ name: name, param: param });}).catch((error: BusinessError) => {logger.error(`promise import module failed, error code:${error.code}, message:${error.message}`);});} else {DynamicsRouter.navPathStack.pushPath({ name: name, param: param });DynamicsRouter.pushRouterStack(routerInfo);} }
-
注册动态路由跳转的页面信息
public static registerAppRouterPage(routerInfo: AppRouterInfo, wrapBuilder: WrappedBuilder<[object]>): void {const builderName: string = routerInfo.name;if (!DynamicsRouter.builderMap.has(builderName)) {DynamicsRouter.registerBuilder(builderName, wrapBuilder);} }
动态路由的使用
-
在工程的hvigor/hvigor-config.json5中配置插件
{..."dependencies": {..."@app/ets-generator": "file:../plugin/AutoBuildRouter"} }
-
在工程的根目录的build-profile.json5中添加动态路由模块和需要加载的子模块的依赖,详细代码参考build-profile.json5。
{"app":{...}"modules":{...{"name": "eventpropagation","srcPath": "./feature/eventpropagation"},{"name": "routermodule","srcPath": "./common/routermodule"}...} }
-
在主模块中添加动态路由和需要加载的子模块的依赖,详细代码请参考oh-package.json。
"dependencies": {"@ohos/dynamicsrouter": "file:../../common/routermodule", "@ohos/event-propagation": "file:../../feature/eventpropagation",... }
-
在主模块中添加动态import变量表达式需要的参数,此处在packages中配置的模块名必须和oh-package.json中配置的名称相同,详细代码请参考build-profile.json5。
... "buildOption": {"arkOptions": {"runtimeOnly": {"packages": ["@ohos/event-propagation",...]}} }
-
在主模块EntryAbility的onCreate接口初始化动态路由,详细代码请参考EntryAbility.ets。
... onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {DynamicsRouter.routerInit({libPrefix: "@ohos", mapPath: "routerMap"}, this.context);... } ...
-
在主模块的WaterFlowData.ets中,将子模块要加载的页面,添加到列表中,详细代码请参考WaterFlowData.ets和SceneModuleInfo。
export const waterFlowData: SceneModuleInfo[] = [...new SceneModuleInfo($r('app.media.address_exchange'), '地址交换动画', new RouterInfo("", ""), '动效', 2, "addressexchange/AddressExchangeView"),... }
-
在需要加载时将页面放入路由栈,详细代码请参考FunctionalScenes.ets。
@Builder methodPoints(listData: ListData) {Column() {....onClick(() => {...DynamicsRouter.pushUri(this.listData.appUri);...}) }
-
在子模块中添加动态路由的依赖,详细代码可参考oh-package.json。
... "dependencies": {..."@ohos/dynamicsrouter": "file:../../common/routermodule" }
以上是需要在主模块中添加的配置,如果已经添加过相关代码,则可以直接略过,按照下面的步骤在子模块中添加相关即可自动生成动态路由相关文件。
-
在子模块的oh-package.json5中添加路由模块依赖,可参考oh-package.json5
{..."dependencies": {...// 动态路由模块,用于配置动态路由"@ohos/dynamicsrouter": "file:../../common/routermodule"} }
-
在子模块的hvigorfile.ts文件中添加插件配置,可参考hvigorfile.ts
... import { PluginConfig, etsGeneratorPlugin } from '@app/ets-generator'; // 配置路由信息 const config: PluginConfig = {// 需要扫描的文件的路径,即配置自定义装饰AppRouter的文件路径scanFiles: ["src/main/ets/view/AddressExchangeView"] }export default {...plugins: [etsGeneratorPlugin(config)] /* Custom plugin to extend the functionality of Hvigor. */ }
-
在需要跳转的页面的自定义组件上添加装饰器,可参考AddressExchangeView.ets,如果需要通过路由传递参数,则需要设置hasParam为true,可参考NavigationParameterTransferView.ets。
// 自定义装饰器,用于自动生成动态路由代码及页面的跳转。命名规则:模块名/自定义组件名 @AppRouter({ name: "addressexchange/AddressExchangeView" }) @Component export struct AddressExchangeView {... }
高性能知识点
本示例使用动态import的方式加载模块,只有需要进入页面时才加载对应的模块,减少主页面启动时间和初始化效率,减少内存的占用。
工程结构&模块类型
routermodule // har类型
|---annotation
|---|---AppRouter.ets // 自定义装饰器
|---constants
| |---RouterInfo.ets // 路由信息类,用于配置动态路由跳转页面的名称和模块名(后续会删除)
|---model
| |---AppRouterInfo.ets // 路由信息类
| |---RouterParam.ets // 路由参数
|---router
| |---DynamicsRouter.ets // 动态路由实现类
|---util
| |---RouterLoader.ets // 路由表加载类
模块依赖
不涉及
参考资料
动态路由Sample
FAQ
Q:动态路由用起来比较麻烦,为什么不直接使用系统提供的页面路由,而是要重写一套路由栈管理?
A:系统层面现在提供了两种方式进行页面跳转,分别是页面路由 (@ohos.router)和组件导航 (Navigation)。这两种方式用起来都比较简单,但是Router相较于Navigation缺少很多能力(具体可参考Router和Navigation能力对标),所以目前应用开发中推荐使用Navigation进行页面跳转。
而使用Navigation时存在一个问题,需要将跳转的子页面组件通过import的方式引入,即不论子页面是否被跳转,都会使子页面引用的部分组件被初始化。例如页面A使用Navigation跳转到页面B,页面B中有用到Web组件加载一个H5页面。那么当进入页面A时,就会初始化Web组件相关的so库。即使用户只是在页面A停留,并没有进入页面B,也会在进入页面A时多出一部分初始化so库的时间和内存。这是因为在页面A中会直接import页面B的自定义组件,导致so库提前初始化。这样就会导致主页面启动耗时延长,以及不必要的内存消耗。
由于动态路由使用了动态import实现,可以很好的避免这种情况的发生。只有在进入子页面时,才会去初始化子页面的相关组件,减少主页面的启动时间和内存占用,提升性能。而且由于使用了自定义路由栈,可以定制业务上的需求,更好的进行管理。
当主页面中需要跳转的子页面较少时,使用Navigation更加方便。反之,则更推荐使用动态路由进行跳转。
最后
小编在之前的鸿蒙系统扫盲中,有很多朋友给我留言,有很多小伙伴不知道学习哪些鸿蒙开发技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?而且学习时频繁踩坑,最终浪费大量时间。所以有一份实用的鸿蒙(HarmonyOS NEXT)路线图、学习视频、文档用来跟着学习是非常有必要的。
如果你是一名有经验的资深Android移动开发、Java开发、前端开发、对鸿蒙感兴趣以及转行人员
鸿蒙 NEXT 全栈开发学习笔记 希望这一份鸿蒙学习文档能够给大家带来帮助~
鸿蒙(HarmonyOS NEXT)最新学习路线
该路线图包含基础技能、就业必备技能、多媒体技术、六大电商APP、进阶高级技能、实战就业级设备开发,不仅补充了华为官网未涉及的解决方案
路线图适合人群:
IT开发人员:想要拓展职业边界
零基础小白:鸿蒙爱好者,希望从0到1学习,增加一项技能。
技术提升/进阶跳槽:发展瓶颈期,提升职场竞争力,快速掌握鸿蒙技术
2.视频学习教程+学习PDF文档
HarmonyOS Next 最新全套视频教程
纯血版鸿蒙全套学习文档(面试、文档、全套视频等)
总结
参与鸿蒙开发,你要先认清适合你的方向,如果是想从事鸿蒙应用开发方向的话,可以参考本文的学习路径,简单来说就是:为了确保高效学习,建议规划清晰的学习路线