一、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);}});});}这段代码做了三件事:
- 获取安全区域尺寸:读取状态栏和导航条的高度,存储到
GlobalInfoModel - 监听窗口变化:适配折叠屏等场景下的尺寸变化
- 监听安全区域变化:适配键盘弹起等动态场景
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 的实现。