销毁地图
背景
在页面切换的时候,如果连续跳转的页面都使用了地图组件,对于地图组件的释放必须遵循“先销毁后创建”的栈式语义。
路由框架分类与处理策略
1) 已知“栈式下发”的路由框架(系统Router 框架)
• 特性:生命周期严格按栈式下发,aboutToDisappear可靠早于对端出现。
• 建议:地图组件在收到aboutToDisappear时可安全自我销毁,开发者无需关注。
2) 已知支持“可打断动画”的路由框架(系统Navigation、HMRouter框架等)
• 特性:为支持打断/反转,aboutToAppear可能早于前一页的aboutToDisappear。
• 风险:若仅依赖aboutToDisappear,销毁会被动画延后,影响严格的栈式释放。
• 建议(必须执行):在旧页面的onWillDisappear主动调用当前地图实例的onWillDisappear()。
2.1) 开发指导
场景A (新建工程,Navigation)
• MapComponent 的 onReady 回调中获取 MapController。
• 页面 NavDestination 的 onWillDisappear 生命周期回调中,调用 mapController.onWillDisappear()。
import { MapComponent, MapController} from "@bdmap/map"import { AsyncCallback } from "@kit.BasicServicesKit";@Builderexport function MapPageOneBuilder(name: string, param: Object) {MapPageOneComponent();}@Componentstruct MapPageOneComponent {private stack: NavPathStack | null = null;@State eventStr: string = "";mapController: MapController | null = nullprivate onReady: AsyncCallback<MapController> = async (err, mapCtrl) => {if (mapCtrl) {this.mapController = mapCtrl}}build() {NavDestination() {Column() {MapComponent({onReady: this.onReady}).height('70%')Button('pushPath', { stateEffect: true, type: ButtonType.Capsule }).width('80%').height(40).margin(20).onClick(() => {if (this.stack) {this.stack.pushPath({ name: "MapPageOne" });}})Button('pop', { stateEffect: true, type: ButtonType.Capsule }).width('80%').height(40).margin(20).onClick(() => {this.stack?.pop();})}.width('100%').height('100%')}.title('pageOne').onWillDisappear(() => {this.mapController?.onWillDisappear()}).onReady((ctx: NavDestinationContext) => {try {this.eventStr += "<onReady>";this.stack = ctx.pathStack;} catch (e) {console.error(`testTag onReady catch exception: ${JSON.stringify(e)}`);}})}}
示例源码:
场景B(既有工程,HMRouter)
• 核心思路:维护“当前活跃地图”的全局列表。通过 HMRouter 注册全局生命周期监听,当收到 onWillDisappear 时,遍历全局列表并逐个触发控制器的销毁入口,随后清空列表。
• 全局状态:保存活跃的 MapController:
// Global.ets(示例)import { MapController } from "@bdmap/map_walkride_search";export class GlobalState {public static context: Context;public static mapControllers: Array<MapController> = [];public static destroyMapControllers () {GlobalState.mapControllers.forEach((controller: MapController): void => controller?.onWillDisappear());GlobalState.mapControllers.length = 0;}}// MapComponentPage.ets(示例)@Componentexport struct MapComponentPage {build() {Stack({ alignContent: Alignment.TopStart }) {MapComponent({onReady: (err, mapController: MapController) => {if (mapController) {// 保存到全局列表GlobalState.mapControllers.push(mapController)}}}).width('100%').height('100%')}.width('100%').height('100%')}}
HMRouter 注册全局生命周期监听
// PageDurationLifecycle.ets(示例)export class PageDurationLifecycle implements IHMLifecycle {onShown(ctx: HMLifecycleContext): void {const pageName = ctx.navContext?.pathInfo.name;console.log('PageDurationLifecycle',`Page ${pageName} onShown at ${new Date()}`);}onWillDisappear(ctx: HMLifecycleContext): void {const pageName = ctx.navContext?.pathInfo.name;console.log('PageDurationLifecycle',`Page ${pageName} onWillDisappear at ${new Date()}`);console.log(`PageDurationLifecycle::DestroyMapControllers GlobalState.mapControllers.length: ${GlobalState.mapControllers.length}`);// 收到回调触发销毁GlobalState.destroyMapControllers();}onHidden(ctx: HMLifecycleContext): void {const pageName = ctx.navContext?.pathInfo.name;console.log('PageDurationLifecycle',`Page ${pageName} onHidden at ${new Date()}`);}}}// Index.ets(示例)import { HMDefaultGlobalAnimator, HMNavigation, HMRouterMgr } from '@hadss/hmrouter';import { AttributeUpdater } from '@kit.ArkUI';import { PageDurationLifecycle } from '../common/PageDurationLifecycle';@Entry@Componentstruct Index {modifier: MyNavModifier = new MyNavModifier();aboutToAppear(): void {HMRouterMgr.registerGlobalLifecycle({lifecycle: new PageDurationLifecycle(),lifecycleName: 'PageDurationLifecycle',priority: 5});}build() {Column() {HMNavigation({navigationId: 'mainNavigation',homePageUrl: 'your_home_url',options: {standardAnimator: HMDefaultGlobalAnimator.STANDARD_ANIMATOR,dialogAnimator: HMDefaultGlobalAnimator.DIALOG_ANIMATOR,modifier: this.modifier}})}.width('100%').height('100%')}}
3) 其他第三方路由框架(时序特征不一)
说明:不同框架的转场实现与动画调度差异较大,生命周期回调先后可能与系统 Router/Navigation 不同。
建议(通用安全方案):
• 在“页面将离场”的回调(如onWillDisappear或框架提供的等效钩子)调用onWillDisappear(),确保地图生命周期以栈式语义执行。
• 如框架支持“动画可打断/反转”,务必采用第2 类方案。
上一篇
下一篇
本篇文章对您是否有帮助?