当前位置: 首页 > news >正文

04 Stage 模型、系统能力与数据架构

一、详细知识点

1. UIAbility

UIAbility是带 UI 的应用组件,负责生命周期入口。常见回调包括创建、窗口创建、前台、后台和销毁。

exportdefaultclassEntryAbilityextendsUIAbility{onWindowStageCreate(windowStage:window.WindowStage):void{windowStage.loadContent('pages/Index')}}

2. WindowStage

WindowStage负责窗口管理和页面加载。首页路径错、资源错或页面构建异常,都可能表现为启动失败或白屏。

3. Context

Context是访问资源、文件、系统能力和运行环境的重要入口。工程化开发要明确 Context 生命周期,不要把短生命周期对象长期持有。

4. 页面导航

简单 demo 可用页面状态切换;生产项目应使用官方推荐导航能力组织页面栈、参数和返回行为。无论哪种方式,都要处理参数缺失和数据不存在。

5. 权限与系统能力

调用网络、位置、媒体、通知等能力时,要先声明权限,再按场景申请或检查。用户拒绝权限是正常路径,必须给替代方案。

6. 数据架构

Page 页面

Component 组件

Service 业务服务

Remote API / Mock API

Local Store / Preferences

Model 类型模型

工程要求:

  • Page 只做展示和交互。
  • Service 负责业务编排。
  • Store 负责本地状态和持久化。
  • Remote API 负责网络请求。
  • Model 做边界转换,避免脏数据进入 UI。

二、本章 demo

Demo 1:生命周期日志

EntryAbility.ets中记录生命周期:

onForeground():void{hilog.info(0x0000,'HarmonyNews','onForeground')}onBackground():void{hilog.info(0x0000,'HarmonyNews','onBackground')}

Demo 2:收藏状态封装

FavoriteStore.ets

statictoggle(articleId:string):void{if(FavoriteStore.favoriteIds.has(articleId)){FavoriteStore.favoriteIds.delete(articleId)}else{FavoriteStore.favoriteIds.add(articleId)}}

Demo 3:页面只调用服务

Index.ets不直接维护收藏集合,而是调用FavoriteStore.toggle()NewsService.markFavorites(),保持页面薄。

三、面试题与详细答案

1.UIAbility和页面是什么关系?

UIAbility是应用组件入口,负责生命周期和窗口创建;页面是 ArkUI 渲染内容。UIAbility通过WindowStage.loadContent()加载页面。页面不应该承担应用生命周期管理职责。

2. 为什么不能在生命周期里做重任务?

生命周期回调影响启动和前后台切换,如果做长时间同步任务会造成首屏慢、卡顿甚至 ANR 风险。重任务应拆到异步流程,首屏只做必要初始化。

3. 权限拒绝时应该怎么处理?

权限拒绝是用户选择,不是程序异常。应用应解释原因、提供降级能力、允许稍后再开启,而不是直接崩溃或强制退出。

4. Repository / Service 分层解决什么问题?

它把页面和数据源解耦。页面不关心数据来自网络、缓存还是 mock;测试时可以替换 Service;接口变更时集中修改转换逻辑。这是从 demo 走向生产工程的关键。

四、五倍扩展知识点矩阵

1. Stage 模型对象关系

对象职责常见使用工程风险
UIAbilityUI 应用组件入口生命周期、窗口创建生命周期阻塞
WindowStage窗口舞台加载页面页面路径和窗口状态错误
Context上下文资源、文件、系统能力错误持有导致泄漏
Want启动参数跨 Ability 传参参数缺失和类型不匹配
AbilityStageHAP 级初始化模块启动逻辑初始化过重
ExtensionAbility扩展能力卡片、服务等生命周期和权限差异
module.json5模块声明Ability、权限配置与代码不一致
app.json5应用身份包名、版本发布后变更风险
resources资源字符串、颜色、媒体多语言和主题治理
hilog日志生命周期和错误敏感信息泄露

2. 生命周期实践

回调适合做不适合做
onCreate轻量初始化、日志网络大请求、重 IO
onWindowStageCreate加载首页、窗口配置业务批处理
onForeground恢复监听、刷新短期状态重复创建资源
onBackground保存草稿、暂停任务开启新长任务
onDestroy清理资源发起不可控异步

生产实践理解:生命周期不是业务万能入口。它是应用运行状态变化的边界,业务初始化要分级:首屏必要、首屏后、用户触发、后台可延迟。

3. 权限治理

权限场景产品问题技术问题合规问题
网络为什么需要联网失败和超时数据传输说明
位置是否必须精准定位授权拒绝降级高敏感信息
相机是否必须拍摄设备无能力用户授权说明
相册是否可替代文件格式最小访问范围
通知是否打扰用户通知开关用户可关闭
麦克风是否必要录音失败明确用途
文件保存在哪里空间不足数据删除
后台任务是否真需要耗电用户感知

4. 数据架构扩展

Page / Component

View State

Service / UseCase

Repository

Remote API

Local Store

DTO Mapper

Error Mapping

分层解释:

  • Page 只关心展示状态。
  • View State 组合 loading、error、data。
  • Service 表达业务动作,如刷新、收藏、保存设置。
  • Repository 屏蔽远程和本地数据源。
  • Mapper 处理 DTO 到领域模型。
  • Error Mapping 把底层错误变成用户可理解状态。

5. 缓存策略

策略适合场景风险
只读远程实时性强弱网体验差
先缓存后网络新闻、配置数据可能短暂旧
只本地设置、草稿多端同步差
写穿缓存写后马上读写失败处理复杂
定时刷新首页推荐耗电和流量
用户触发刷新列表页用户等待
分页缓存长列表缓存清理
版本化缓存数据结构升级迁移成本

五、系统能力 demo 扩展任务

任务目标验证
增加网络权限说明学会权限声明module.json5有权限
模拟 HTTP 失败学会错误状态页面显示重试
增加缓存读取学会本地优先首屏先显示旧数据
增加设置持久化学会 Preferences 思路重启后保留设置
增加权限拒绝文案学会降级用户知道原因
增加详情参数校验防止空参数缺 id 显示空状态
增加刷新节流防重复请求连点不重复发起
增加 Repository解耦页面和数据源Page 不知道 mock
增加错误码映射技术错误转业务错误页面文案清晰
增加日志 traceId排查链路日志能串起来

扩展示例:Repository 接口

exportinterfaceNewsRepository{queryArticles():Promise<NewsArticle[]>queryArticleById(id:string):Promise<NewsArticle|undefined>toggleFavorite(id:string):Promise<void>}

接口化后,页面可以依赖抽象,测试时使用 FakeRepository,生产时使用 RemoteRepository + LocalStore。

六、数据流检查

检查项好的表现坏的表现
数据来源页面知道状态,不知道接口细节页面直接拼接口
错误处理分技术错误和用户文案catch后静默
缓存有版本和失效策略永久保存不清理
权限拒绝可降级拒绝就崩溃
日志有模块和动作只有 error
安全不记录敏感信息token 写日志
测试Service 可替换只能真机点
并发处理重复请求状态互相覆盖
恢复前后台状态合理返回页面错乱
扩展新数据源容易接页面大改

七、扩展面试题

5. Stage 模型里为什么要区分 Ability 生命周期和页面生命周期?

Ability 生命周期描述应用组件的运行状态,页面生命周期描述 UI 组件的出现和消失。二者粒度不同。把页面数据加载都塞进 Ability 会让入口过重;把应用级资源管理放进页面又会导致重复初始化。

6. 权限最小化如何落地?

先从业务需求反推权限,能不用就不用,能低敏就不用高敏。配置文件只声明真实需要的权限,运行时在用户触发相关功能时申请,并提供拒绝后的降级路径。上线前检查权限说明和实际使用是否一致。

7. Repository 和 Store 的区别是什么?

Repository 负责统一数据访问,可以组合远程、本地和转换逻辑;Store 更偏本地状态或持久化状态管理。Repository 可以使用 Store,但页面最好通过 Service 或 Repository 获取业务数据。

8. 如何设计弱网体验?

首屏尽量展示缓存;请求要有超时;失败要有重试;关键操作要有明确状态;不要无限转圈。对于写操作,要说明是否成功、是否可重试、是否会重复提交。

9. Context 为什么不能随意长期持有?

Context 和运行环境、Ability 生命周期有关。随意长期持有可能造成生命周期错乱或资源无法释放。需要系统能力时应在合适作用域获取,并避免把短生命周期对象保存到全局单例中。

10. 如何从 demo 架构演进到生产架构?

先把 mock 数据移入 Service,再抽 Repository,再增加 LocalStore 和 RemoteAPI,再统一错误处理和日志,最后补测试和发布检查。每一步都保持页面调用方式稳定,避免 UI 随数据源变化大改。

八、Stage 与数据架构详解库

1. 生命周期是资源管理边界

前后台切换、窗口创建和销毁决定了资源何时创建、暂停、恢复和释放。网络轮询、动画、定位、监听器等都要和生命周期绑定,否则会带来耗电、内存和状态问题。

2. 首屏初始化要分级

首屏必要任务包括加载首页、读取最低限度设置、准备关键 UI。非必要任务如预加载推荐、同步历史、上传日志应延后。启动阶段越重,用户感知越差。

3. Want 参数必须校验

跨 Ability 或页面传参时,参数可能缺失、类型不对或来自旧版本。详情页根据 id 加载数据时,必须处理 id 为空和文章不存在。

4. 权限申请要绑定用户动作

应用启动就申请大量权限体验很差。更好的方式是在用户触发相关功能时说明原因并申请。拒绝后提供降级路径。

5. Repository 是数据源防火墙

页面不应该知道数据来自 mock、HTTP、缓存还是数据库。Repository 隐藏这些细节,让页面只处理业务状态。

6. 本地缓存要有失效策略

缓存不是永久保存。新闻列表可以设置时间失效,用户设置可以长期保存,登录态和敏感信息要按安全策略管理。

7. 弱网不是异常边角

移动应用大量场景都可能弱网。架构要内置超时、重试、缓存、错误提示和重复提交保护。

8. 日志要串联链路

一次用户操作可能经过 Page、Service、Repository、Remote 和 Store。日志如果没有 traceId 或上下文,很难定位问题发生在哪一层。

9. 多设备能力要先抽象

不同设备能力不同,页面不应直接假设所有系统能力都可用。要有能力检测、降级和设备差异策略。

10. 架构演进要小步保持可运行

不要一次性把 demo 重构成复杂架构。每次只引入一个边界:先 Service,再 Store,再 Repository,再 Remote。每一步都保持项目可运行。

九、Stage 与系统能力场景库

场景架构动作风险验收
启动首页Ability 加载页面白屏首页显示
前台恢复刷新短状态重复请求日志清楚
后台切换保存草稿数据丢失返回恢复
打开详情校验 id空参数空状态
请求新闻Service 调 Repository网络失败重试
收藏文章Store 更新状态不同步列表和收藏页一致
设置主题Store 持久化重启丢失重新打开保留
权限拒绝降级提示崩溃用户可返回
缓存过期重新拉取旧数据有刷新策略
弱网超时错误映射无限加载出现提示
多设备能力检测调用失败降级可用
日志追踪traceId无法定位链路可串

十、扩展面试题库

11. 为什么首屏不应该等待所有接口?

用户首先需要看到可交互界面。等待所有接口会放大最慢接口的影响。应优先加载首屏必要数据,非关键数据延后或并发加载。

12. 如何设计缓存失效?

根据数据性质决定。新闻列表可以短时间缓存并允许手动刷新;用户设置长期有效;敏感数据要有安全和清理策略。缓存要记录版本和时间,避免旧结构解析失败。

13. 弱网下如何避免重复提交?

按钮点击后进入提交中状态,禁用重复点击;请求带业务幂等标识;失败时明确是否可重试;重试不能造成重复业务结果。

14. 为什么权限弹窗要延后到具体场景?

用户在具体场景下更容易理解权限用途。启动即申请会让用户困惑,也可能导致拒绝率上升。延后申请还能减少不必要权限。

15. 如何判断架构是否过度设计?

如果抽象没有减少重复、没有隔离变化、没有提升测试性,只是增加文件和跳转,就是过度设计。架构应服务当前复杂度,并允许未来平滑扩展。

十一、系统能力知识体系补全

能力域关键能力封装建议验收点
应用框架UIAbility、ExtensionAbility、Want、ContextAbilityService生命周期日志完整
导航与启动router、Navigation、深链、Want 参数NavigationService参数缺失可恢复
权限声明、申请、拒绝、撤回PermissionService拒绝不崩溃
网络HTTP、超时、重试、弱网HttpClient失败有错误映射
数据存储Preferences、文件、relationalStoreLocalDataSource缓存可读写
媒体图片、相册、音视频、拍摄MediaService授权和失败处理
通知通知权限、频道、点击跳转NotificationService可开启可关闭
后台任务短任务、延迟任务、WorkScheduler 类场景BackgroundTaskService不滥用后台
并发taskpool、worker、异步队列TaskServiceUI 不阻塞
设备能力窗口、屏幕、设备类型、传感器DeviceService多设备可降级
卡片FormExtensionAbility、卡片数据刷新WidgetService卡片独立可用
分布式/协同多设备流转、数据协同场景CollaborationService状态迁移清楚
日志hilog、traceId、分级Logger日志可串联

十二、数据架构分层方案

Page / Component

ViewState

UseCase / Service

Repository Interface

RemoteDataSource

LocalDataSource

MemoryCache

DTO

Mapper

Domain Model

ErrorMapper

职责说明:

  • ViewState描述页面状态,不直接描述网络细节。
  • UseCase表达业务动作,如刷新新闻、收藏文章、保存设置。
  • Repository屏蔽数据源,页面不关心远程还是本地。
  • RemoteDataSource只负责请求和响应 DTO。
  • LocalDataSource负责 Preferences、文件或数据库。
  • Mapper把 DTO 转成领域模型。
  • ErrorMapper把系统错误转成业务错误。

十三、持久化选型

数据推荐方式原因注意
主题、字号Preferences小数据、读取快版本迁移
收藏 idPreferences 或数据库数据简单数量增长时迁移
新闻缓存文件或数据库数据较多失效策略
阅读历史数据库可查询、可分页清理策略
草稿文件/数据库需要恢复防损坏
登录态安全存储能力敏感不能明文
图片缓存文件缓存体积大容量上限
配置Preferences + 远程配置快速读取灰度生效

十四、并发与后台任务

场景推荐策略风险
首页并行加载并发请求错误聚合
图片处理worker/taskpool线程通信成本
大列表计算后台计算 + 分批更新旧任务覆盖新任务
定时刷新按需触发耗电
日志上传延迟或批量隐私和流量
离线同步队列重复提交
搜索防抖延迟触发响应延迟

并发设计要先保证正确性,再考虑速度。所有后台结果回到 UI 前都要校验页面是否仍需要该结果。

十五、架构设计文档模板

1. 业务目标 2. 页面范围 3. 模块划分 4. 数据模型 5. 状态流 6. 网络和缓存策略 7. 权限和系统能力 8. 错误处理 9. 性能风险 10. 安全和隐私 11. 测试方案 12. 发布和回滚

项目达到一定规模后,每个核心功能都应有轻量设计文档。没有设计文档,后续维护只能靠读代码猜意图。

十六、架构练习套件

练习目标验收
抽 Repository页面不关心数据源可切换 mock/remote
加 Preferences设置持久化重启保留
加数据库设计阅读历史分页可查询可删除
加权限服务统一申请拒绝可降级
加通知服务收藏更新提醒可关闭
加后台队列日志批量上传不阻塞 UI
加错误映射系统错误转业务文案文案统一
加 traceId请求链路追踪日志可关联
加模块边界feature/common 分层依赖方向正确
加架构图说明系统结构新人能读懂

十七、补充面试题

16. 如何给鸿蒙应用设计数据层?

先定义领域模型,再定义 Repository 接口,然后实现 RemoteDataSource、LocalDataSource 和 Mapper。页面只依赖业务服务,不直接接触 HTTP、Preferences 或数据库。

17. Preferences 和数据库如何选择?

Preferences 适合少量 key-value 数据,如设置和轻量状态;数据库适合结构化、可查询、可分页的数据,如阅读历史、离线列表。选择时看数据量、查询方式、更新频率和迁移成本。

18. 系统能力为什么要统一封装?

权限、通知、媒体、文件等系统能力都有失败路径和设备差异。统一封装可以集中处理权限、日志、错误映射和降级,避免页面到处散落系统 API。

19. 如何设计模块依赖方向?

业务 feature 可以依赖 common-ui、common-model、common-data,但 common 不能反向依赖 feature。数据层不能依赖 UI。依赖方向越单向,项目越容易扩展和测试。

20. 架构设计如何避免空谈?

每个架构结论都要落到文件结构、接口定义、数据流、错误处理和测试方式。只画图不落代码约束,就不能指导开发。

http://www.jsqmd.com/news/790050/

相关文章:

  • yuzu模拟器完整指南:免费在电脑上玩Switch游戏的终极教程
  • 从SD协议到FatFs:深入解析Block与Sector的映射关系及disk_ioctl实战指南
  • 缓存命中率从38%飙至91.6%,我们复刻了SITS大会TOP3团队的动态分片缓存方案,
  • 3步快速解决Windows和Office激活难题:KMS智能激活终极方案
  • 游戏地图开发者的利器:手把手教你用MapCutter为Unity/Web游戏制作无缝瓦片地图
  • 深度实战:如何用SpliceAI深度学习工具精准预测基因剪接变异
  • 观察大模型API调用延迟体验Taotoken全球直连网络的稳定性
  • 终极指南:如何用Ofd2Pdf轻松实现OFD转PDF的完整解决方案
  • 用DyberPet桌面宠物框架打造你的专属数字伙伴:从零开始的全新体验
  • 2026石英式动态称重传感器品牌推荐,广州晶石,一致好评的实力厂家 - 品牌速递
  • 从理论到实践:深入解析PnP算法及其在视觉SLAM中的应用
  • Navicat Mac版试用期重置终极指南:3种简单方法无限使用
  • 5款VeLoCity皮肤:让你的VLC播放器焕然一新的终极美化指南
  • 如何实现WPS与Zotero无缝对接:5个技巧让科研写作效率飙升
  • 通过终端命令行与OpenClaw AI助手控制特斯拉:自动化与能源管理实战
  • 别再只调API了!用C++和Tesseract 5.x实现一个带置信度过滤的OCR小工具
  • 3步快速解决Mac读写NTFS硬盘难题:Nigate免费工具终极指南
  • 5分钟快速上手:在Blender中使用3MF格式的完整指南
  • 亨得利深圳高端腕表抛光翻新全程实录:2026年官方售后网点深度测评与避坑指南(附全国授权门店地址) - 亨得利腕表维修中心
  • Faster-Whisper-GUI:免费开源的终极语音转文字工具,5分钟上手高质量音频转录
  • Awoo Installer深度解析:Switch游戏安装工具的技术原理与实战应用
  • 深度解析B站视频下载器:技术架构与实战应用指南
  • Oh My Zsh插件安装踩坑实录:手把手解决autojump在Mac和Ubuntu下的配置问题
  • 自主智能体系统结构化日志方案:基于OpenClaw的agent-logger实践
  • AI配置安全扫描:ferret-scan如何守护你的AI助手开发环境
  • 2026年广州留学中介机构口碑之选:五家优选深度解析 - 科技焦点
  • 纽雀信与清华大学联合发表AI领域国际顶刊论文 - 博客湾
  • FramePack终极指南:如何用恒定上下文压缩技术实现高效视频生成
  • LizzieYzy:免费开源围棋AI分析工具终极指南
  • SITS 2026到底值不值得去?一线技术负责人亲测对比:去年参会者87%在Q3完成模型推理成本压降≥42%