这一章只看一件事:应用为什么能先把服务层准备好,再把首页稳稳地加载出来。

图 4-1 章首页封面:Stage 模型入口与首页加载链路
|
维度 |
内容 |
|
本章主题 |
EntryAbility 如何在 Stage 模型下把“留痕”带到首页 |
|
核心源码 |
EntryAbility.ets、main_pages.json、module.json5、WorkClockService.ets、Index.ets |
|
阅读目标 |
看懂启动链路、配置职责和首页数据为什么能在启动后直接出现 |
|
先给结论在 Stage 模型里,真正的入口不是首页页面本身,而是 EntryAbility。EntryAbility 负责先 bootstrap,再 loadContent,首页只是最后被加载出来的那一页。 |
一、Stage 模型下,真正的入口是 EntryAbility
在这个项目里,应用从桌面图标被点开之后,最先被系统调用的是 EntryAbility。它不是一个普通页面,而是负责把应用从“启动态”切换到“可见态”的第一道闸门。这个阶段如果没有把服务层和窗口链路准备好,首页就算能渲染出来,也只会是一张空壳。
|
import { AbilityConstant, ConfigurationConstant, UIAbility, Want } from '@kit.AbilityKit'; export default class EntryAbility extends UIAbility { onWindowStageCreate(windowStage: window.WindowStage): void { |
|
阶段 |
关键动作 |
效果 |
|
onCreate |
先切换颜色模式,再调用 WorkClockService.bootstrap() |
服务层在首页出现之前完成准备 |
|
onWindowStageCreate |
通过 Routes.MAIN_PAGE 加载首页 |
入口和页面路由保持统一 |
|
loadContent 失败 |
记录 hilog 日志 |
便于定位白屏或路由错误 |

图 4-2 启动链路:系统启动 -> EntryAbility -> bootstrap -> 首页
二、先 bootstrap,再 loadContent
EntryAbility.onCreate 里最关键的动作不是页面渲染,而是 WorkClockService.bootstrap。它把本地持久化数据、默认模板和 AppStorage 状态先准备好,再把首页交给 windowStage.loadContent。这样做的好处很直接:首页第一次进入时拿到的就是可用数据,而不是临时拼出来的默认壳。
|
bootstrap(context: common.UIAbilityContext): void { const raw: string = WorkClockRepository.readState(); this.publishSelectedWatermarkSnapshot(); |
|
步骤 |
做什么 |
结果 |
|
初始化 AppStorage |
写入 WORKCLOCK_VERSION 和 MAIN_TAB |
首页和服务层有统一的轻量状态入口 |
|
读取持久化状态 |
从 WorkClockRepository 取回 JSON |
已有记录和模板可以直接恢复 |
|
回填默认值 |
当本地没有数据时装入默认模板和分类 |
首次安装也不会空白 |
|
发布水印快照 |
把当前模板写回 AppStorage |
水印页和拍照页能同步读取 |
|
这一段的关键bootstrap 不是“初始化一下就完了”,而是把首页需要的默认状态、模板快照和持久化入口一次性搭好。首页之所以能直接展示内容,是因为这一步已经先把底子铺好了。 |
三、main_pages.json 和 module.json5 各管一半
页面清单和 Ability 配置是两层职责。main_pages.json 只告诉系统哪些页面可以被加载,module.json5 则负责声明入口 Ability、权限和启动能力。两份文件各管一半,缺一块都不行。
|
{ |
|
{ |

图 4-3 配置关系:main_pages.json、module.json5 与 EntryAbility 的分工
|
配置项 |
作用 |
本章关注点 |
|
mainElement |
指向入口 Ability |
系统先找到 EntryAbility,再决定加载什么页面 |
|
pages |
绑定页面清单 |
首页和功能页都从这里被注册 |
|
requestPermissions |
声明运行权限 |
相机、麦克风和定位都在这里提前声明 |
|
skills / actions |
支持桌面入口 |
保证桌面点击能够进入应用 |
四、首页为什么一打开就有数据
首页不是自己去拉一份孤立的数据,而是通过 AppStorage 里的轻量状态和服务层的快照来渲染。WorkClockService 负责维护真实数据,Index 负责在页面生命周期里把这些数据读出来,再渲染成首页、记录和统计卡片。
|
export class AppStorageKeys { |
|
@StorageLink(AppStorageKeys.WORKCLOCK_VERSION) aboutToAppear(): void { onPageShow(): void { private refreshAllData(resetCalendarDate: boolean): void { this.overview = this.service.getOverviewSnapshot(); |
|
private bumpVersion(): void { |
|
Key |
写入方 |
读取方 |
|
MAIN_TAB |
WorkClockService.bootstrap / Index.switchTab |
Index.refreshAllData |
|
WORKCLOCK_VERSION |
WorkClockService.bumpVersion |
Index.@StorageLink + @Watch |
|
WATERMARK_TEMPLATE_ID |
publishSelectedWatermarkSnapshot |
水印页和拍照页 |
|
WATERMARK_TITLE / NOTE / COLOR |
publishSelectedWatermarkSnapshot |
水印编辑页预览和保存 |
|
一句话记住它AppStorage 不是数据库,它只负责让页面之间共享轻量状态;真正的业务数据仍然由服务层和本地存储负责。 |
五、本章小结
第四章把启动链路真正串了起来:EntryAbility 先做服务初始化,再加载首页;main_pages.json 和 module.json5 各自负责页面清单和入口配置;Index 通过 AppStorage 的版本号和主 Tab 状态,把服务层快照渲染成用户能看到的数据。这样一来,首页一打开就有内容,后面的拍照、录音和记录页也都能沿着同一套状态链路工作。
今日实操
|
步骤 |
检查点 |
完成后看到什么 |
|
查看 EntryAbility |
确认 onCreate 与 onWindowStageCreate 的职责 |
知道应用为什么先进入入口再进入首页 |
|
查看 bootstrap |
确认服务层在首页前完成初始化 |
本地数据和模板快照已经准备好 |
|
查看 Index |
确认 @StorageLink 和 refreshAllData 的作用 |
首页切换和刷新都能跟着版本号走 |
如果你在真机上点开“留痕”,首页能够立刻看到卡片、记录和状态,说明这一章的链路已经跑通了。



