HarmonyOS 实战教程(二):UIAbility 生命周期与全局初始化 —— 以「柚兔自测量表」为例

HarmonyOS 实战教程(二):UIAbility 生命周期与全局初始化 —— 以「柚兔自测量表」为例

一、UIAbility 是什么

UIAbility 是 HarmonyOS 中应用的运行载体,类似于 Android 的 Activity 或 iOS 的 UIViewController,但粒度更粗——一个应用通常只有一个 UIAbility。它负责管理应用的生命周期、窗口创建和资源调度。

MeCharts 应用中定义了EntryAbility,作为整个应用的入口:

import{AbilityConstant,UIAbility,Want}from'@kit.AbilityKit';import{hilog}from'@kit.PerformanceAnalysisKit';import{window}from'@kit.ArkUI';import{WindowUtil}from'../util/WindowUtil';import{PageContext}from'../util/PageContext';import{IBestORMInit}from'@ibestservices/ibest-orm';import{relationalStore}from'@kit.ArkData';constDOMAIN=0x0000;exportdefaultclassEntryAbilityextendsUIAbility{onCreate(want:Want,launchParam:AbilityConstant.LaunchParam):void{hilog.info(DOMAIN,'testTag','%{public}s','Ability onCreate');}onDestroy():void{hilog.info(DOMAIN,'testTag','%{public}s','Ability onDestroy');}onWindowStageCreate(windowStage:window.WindowStage):void{// 初始化 IBest-ORM 数据库IBestORMInit(this.context,{name:"meChart.db",securityLevel:relationalStore.SecurityLevel.S1})// 注册断点监听(响应式布局)WindowUtil.registerBreakPoint(windowStage);// 请求全屏布局WindowUtil.requestFullScreen(windowStage,this.context);// 初始化全局导航上下文AppStorage.setOrCreate('pageContext',newPageContext());// 加载主页面windowStage.loadContent('pages/Index',(err)=>{if(err.code){hilog.error(DOMAIN,'testTag','Failed to load the content. Cause: %{public}s',JSON.stringify(err));return;}hilog.info(DOMAIN,'testTag','Succeeded in loading the content.');});}onWindowStageDestroy():void{hilog.info(DOMAIN,'testTag','%{public}s','Ability onWindowStageDestroy');}onForeground():void{hilog.info(DOMAIN,'testTag','%{public}s','Ability onForeground');}onBackground():void{hilog.info(DOMAIN,'testTag','%{public}s','Ability onBackground');}}

二、生命周期回调详解

2.1 onCreate

onCreate在 Ability 创建时调用,整个生命周期只调用一次。适合做轻量级初始化,如读取传入的 Want 参数。

onCreate(want:Want,launchParam:AbilityConstant.LaunchParam):void{hilog.info(DOMAIN,'testTag','%{public}s','Ability onCreate');}

注意:不要在onCreate中做耗时操作,否则会影响应用启动速度。

2.2 onWindowStageCreate(核心回调)

这是最重要的回调,窗口阶段创建后触发。MeCharts 在此完成了三项关键初始化:

1)数据库初始化

IBestORMInit(this.context,{name:"meChart.db",securityLevel:relationalStore.SecurityLevel.S1})

使用@ibestservices/ibest-orm三方库初始化本地数据库。SecurityLevel.S1表示低安全级别,适合存储非敏感数据(如测评分数记录)。

2)窗口与断点注册

WindowUtil.registerBreakPoint(windowStage);WindowUtil.requestFullScreen(windowStage,this.context);
  • registerBreakPoint:监听窗口尺寸变化,实现响应式布局的断点切换
  • requestFullScreen:设置全屏布局模式,实现沉浸式体验

3)全局状态初始化

AppStorage.setOrCreate('pageContext',newPageContext());

AppStorage是 HarmonyOS 提供的全局状态管理器,类似于全局单例。PageContext封装了导航栈(NavPathStack),所有页面共享同一个导航上下文。

2.3 onForeground / onBackground

onForeground():void{// 应用回到前台}onBackground():void{// 应用退到后台}

适合在此处理资源释放与恢复。例如,AI 聊天页面在后台时可以暂停轮询请求。

2.4 生命周期流程图

应用启动 → onCreate → onWindowStageCreate → onForeground ↓ 应用切到后台 ← onBackground ← 应用运行中 → onForeground → 应用回到前台 ↓ 应用销毁 → onBackground → onWindowStageDestroy → onDestroy

三、全局状态管理:AppStorage

HarmonyOS 提供了AppStorage作为应用级的状态管理中心,MeCharts 中用它管理多个全局状态:

3.1 PageContext —— 全局导航

exportclassPageContextimplementsIPageContext{privatereadonlypathStack:NavPathStack;privatereturnCallback?:(data?:object)=>void;constructor(){this.pathStack=newNavPathStack();}publicopenPage(data:RouterParam,animated:boolean=true):void{this.returnCallback=data.onReturn;this.pathStack.pushPath({name:data.routerName,param:data.param,},animated);}publicpopPage(animated:boolean=true,returnData?:object):void{if(this.returnCallback){this.returnCallback(returnData);this.returnCallback=undefined;}this.pathStack.pop(animated);}publicgetnavPathStack():NavPathStack{returnthis.pathStack;}}

PageContext封装了NavPathStack的操作,提供了统一的页面导航接口。所有页面通过AppStorage获取同一个实例:

privatepageContext:PageContext=AppStorage.get('pageContext')asPageContext;

3.2 GlobalInfoModel —— 全局设备信息

@ObservedexportclassGlobalInfoModel{publiccurrentBreakpoint:BreakpointTypeEnum=BreakpointTypeEnum.MD;publicnaviIndicatorHeight:number=0;publicstatusBarHeight:number=0;publicdecorHeight:number=0;publicdeviceHeight:number=0;publicdeviceWidth:number=0;}

这个模型存储了设备相关的全局信息,包括当前断点、状态栏高度、导航条高度等。在WindowUtil中初始化并持续更新:

constglobalInfoModel:GlobalInfoModel=AppStorage.get('GlobalInfoModel')||newGlobalInfoModel();globalInfoModel.statusBarHeight=px2vp(systemAvoidArea.topRect.height);globalInfoModel.naviIndicatorHeight=px2vp(bottomArea.bottomRect.height);AppStorage.setOrCreate('GlobalInfoModel',globalInfoModel);

在组件中通过@StorageProp装饰器监听变化:

@StorageProp('GlobalInfoModel')globalInfoModel:GlobalInfoModel=AppStorage.get('GlobalInfoModel')!;

3.3 AppStorage 的两种访问方式

装饰器用途是否驱动 UI 刷新
@StorageProp单向绑定,组件内只读
@StorageLink双向绑定,组件内可修改
AppStorage.get/set命令式访问否(需手动触发)

四、沉浸式窗口管理

MeCharts 实现了沉浸式全屏体验,核心逻辑在WindowUtil中:

4.1 设置全屏布局

publicstaticrequestFullScreen(windowStage:window.WindowStage,context:Context):void{windowStage.getMainWindow((err:BusinessError,data:window.Window)=>{constwindowClass:window.Window=data;try{constpromise:Promise<void>=windowClass.setWindowLayoutFullScreen(true);promise.then(()=>{Logger.info(TAG,'Succeeded in setting the window layout to full-screen mode.');});WindowUtil.getDeviceSize(context);}catch{Logger.error(TAG,'Failed to set the window layout to full-screen mode.');}});}

setWindowLayoutFullScreen(true)将窗口内容延伸到状态栏和导航条区域,实现沉浸式效果。

4.2 获取安全区域信息

全屏布局后,需要手动处理安全区域的避让:

publicstaticregisterBreakPoint(windowStage:window.WindowStage){windowStage.getMainWindow((err:BusinessError,data:window.Window)=>{constglobalInfoModel:GlobalInfoModel=AppStorage.get('GlobalInfoModel')||newGlobalInfoModel();// 获取状态栏高度constsystemAvoidArea:window.AvoidArea=data.getWindowAvoidArea(window.AvoidAreaType.TYPE_SYSTEM);globalInfoModel.statusBarHeight=px2vp(systemAvoidArea.topRect.height);// 获取底部导航条高度constbottomArea:window.AvoidArea=data.getWindowAvoidArea(window.AvoidAreaType.TYPE_NAVIGATION_INDICATOR);globalInfoModel.naviIndicatorHeight=px2vp(bottomArea.bottomRect.height);AppStorage.setOrCreate('GlobalInfoModel',globalInfoModel);// 监听窗口尺寸变化data.on('windowSizeChange',()=>WindowUtil.onWindowSizeChange(data));// 监听安全区域变化data.on('avoidAreaChange',(avoidAreaOption)=>{if(avoidAreaOption.type===window.AvoidAreaType.TYPE_SYSTEM||avoidAreaOption.type===window.AvoidAreaType.TYPE_NAVIGATION_INDICATOR){WindowUtil.setAvoidArea(avoidAreaOption.type,avoidAreaOption.area);}});});}

这段代码做了三件事:

  1. 获取安全区域尺寸:读取状态栏和导航条的高度,存储到GlobalInfoModel
  2. 监听窗口变化:适配折叠屏等场景下的尺寸变化
  3. 监听安全区域变化:适配键盘弹起等动态场景

4.3 在组件中使用安全区域

TopBar 组件中,使用statusBarHeight作为顶部 padding:

@ComponentV2exportstruct TopBar{privateglobalInfoModel:GlobalInfoModel=AppStorage.get('GlobalInfoModel')||newGlobalInfoModel();@ParamstatusBarHeight:number=this.globalInfoModel.statusBarHeightbuild(){RelativeContainer(){// ... 标题栏内容}.padding({top:this.statusBarHeight,// 避开状态栏bottom:20,left:12,right:12})}}

五、小结

本篇深入讲解了 UIAbility 的生命周期管理和全局初始化策略。MeCharts 在onWindowStageCreate中集中完成了数据库初始化、窗口配置和全局状态创建,为后续的 UI 渲染奠定了基础。下一篇将讲解 Navigation 导航体系与自定义 TabBar 的实现。