HarmonyOS开发面试题
一、基础概念(必问)
1. HarmonyOS 中 Stage模型 和 FA模型 的区别?为什么推荐Stage?
答案
- FA(Feature Ability):早期模型,PageAbility承载页面,ServiceAbility服务能力,单HAP单进程,页面和能力耦合;能力启动、生命周期管理弱,后台管控差,不支持多HAP、元服务。
- Stage模型:API9+主推模型,拆分 UIAbility(页面能力)+ ExtensionAbility(扩展能力);UIAbility代表应用实例,一个HAP可包含多个UIAbility;支持多HAP、原子化服务、独立Extension、精细化生命周期、更好的系统后台管控。
- 推荐Stage:能力职责解耦、分布式/元服务必备、系统兼容性更好,官方后续不再迭代FA。
2. 什么是Ability?Ability有哪几种类型?各自作用?
答案
Ability是应用可对外提供的能力抽象,Stage下分两大类:
- UIAbility:带界面的能力,对应应用页面实例,可被拉起,拥有前后台生命周期。
- ExtensionAbility:无UI扩展能力,系统回调触发,常见:
- ServiceExtensionAbility:后台服务
- FormExtensionAbility:桌面卡片
- WorkSchedulerExtensionAbility:定时任务
- InputMethodExtensionAbility:输入法
3. AbilityStage的作用,什么时候会创建/销毁?
答案
AbilityStage是HAP模块的运行容器,一个HAP对应一个AbilityStage实例,同HAP内所有UIAbility共享同一个AbilityStage。
- 创建:该HAP下第一个UIAbility启动时创建。
- 销毁:该HAP内所有UIAbility全部销毁后,AbilityStage被系统回收。
用途:存放模块全局资源、全局初始化、监听HAP级别事件。
4. 鸿蒙UI框架:ArkUI声明式与传统JSUI(类Web)的差异。
答案
- JSUI:类Web的标签式开发,JS + HML + CSS,DOM式渲染,性能一般,仅FA模型支持,不再维护。
- ArkUI(声明式):TS/ArkTS直接编写UI,无DOM,编译期生成原生渲染指令,渲染性能更高;天然适配Stage,支持状态驱动、组件复用、自定义装饰器。
5. 简述ArkTS是什么,和TS的区别,限制点有哪些?
答案
ArkTS是TypeScript的超集,为ArkUI定制,在TS基础上增加UI装饰器、状态管理语法;同时增加静态强类型约束。
区别&限制:
- 强制静态类型,不能隐式any;
- 提供
@Component/@State等鸿蒙专属装饰器; - 不支持部分JS动态特性:eval、动态new、动态属性增删;
- 编译阶段做类型校验,提前捕获错误。
6. 什么是元服务(原子化服务),和普通App区别?
答案
元服务(原子化服务):免安装、轻量HAP服务,用户无需安装应用即可直接使用功能,可从服务中心、卡片、二维码拉起。
区别:
- 无桌面图标;免安装,按需下发;
- 包体积限制更小;
- 能力以UIAbility/FormExtension对外提供;
- 不能后台常驻,生命周期由系统严格管控;普通App需要安装,有桌面图标。
7. 包结构:module、hap、app、bundle概念,HAP是什么?
答案
- Module:工程内模块,分为entry模块(入口模块)、feature模块(业务模块);
- HAP(Harmony Ability Package):编译后模块产物,一个module编译输出1个HAP;分为entry HAP(应用入口)、feature HAP(业务分包);
- App:应用逻辑整体;
- App Bundle:打包产物,由多个HAP组成,应用市场分发包。
8. 鸿蒙应用的安装包构成:HAP、app pack、hsap区别。
答案
- HAP:编译后的模块包,可独立调试安装;
- App Pack:发布包,包含多个HAP,应用市场分发原始包;
- HSAP:原子化服务包,轻量免安装包。
9. 应用沙箱是什么,沙箱目录有哪些?各自读写权限。
答案
沙箱:系统给每个应用分配独立隔离目录,应用只能访问自身沙箱,不能随意访问其他应用文件。
常用目录:
context.filesDir:持久私有文件,应用卸载删除,读写;context.cacheDir:缓存目录,系统可自动清理;context.tempDir:临时目录;context.preferencesDir:Preferences存储目录;
媒体公共目录需要申请权限,不属于私有沙箱。
10. 权限分类:系统基础权限、敏感权限,动态申请流程。
答案
- 基础权限:安装时自动授予,无需弹窗(网络等);
- 敏感权限:涉及用户隐私,必须动态申请(相机、位置、存储)。
动态申请流程:
- module.json5 声明权限;
- 代码调用
accessToken.requestPermissions; - 监听授权结果回调;
- 判断是否授权,未授权做降级处理。
11. 简述HiLog,日志级别,开发/发布如何控制日志输出。
答案
HiLog:鸿蒙日志打印工具,替代console。
日志级别(从低到高):DEBUG、INFO、WARN、ERROR、FATAL。
- DEBUG:仅调试使用,release包建议关闭;
- 发布版本通过hilog过滤,关闭debug日志,避免泄露信息。
import hilog from '@ohos.hilog';
// 域id、标签、日志内容
hilog.info(0x0001, "TestTag", "页面加载:%s", "首页");
hilog.error(0x0001, "TestTag", "请求失败");
12. 应用生命周期(UIAbility):Create、Foreground、Background、Destroy,触发时机。
答案
- onCreate:UIAbility实例创建,仅一次,做初始化;
- onForeground:页面切前台,页面可见;
- onBackground:页面切后台,不可见;
- onDestroy:UIAbility销毁,释放资源。
二、ArkUI 核心(高频)
1. @Component、@Entry、@Builder、@BuilderParam 作用与区别。
答案
@Component:标记自定义组件;@Entry:标记页面入口组件,挂载到UIAbility;@Builder:组件内自定义UI构造函数,复用局部UI;@BuilderParam:接收外部传入的@Builder函数,组件插槽能力。
示例代码:
// @Entry标记页面入口
@Entry
@Component
struct PageDemo {
// @Builder 局部UI构造器
@Builder TitleText(title:string) {
Text(title).fontSize(20)
}
build() {
Column() {
this.TitleText("标题")
// 传入builder到子组件
ChildComponent({ titleBuilder: this.TitleText("子标题") })
}
}
}
@Component
struct ChildComponent {
// 接收外部builder
@BuilderParam titleBuilder: ()=>void
build() {
this.titleBuilder()
}
}
2. 状态装饰器:@State / @Prop / @Link / @Watch / @ObjectLink / @Track,各自适用场景,单向/双向数据流。
答案
- @State:组件内部状态,状态变更驱动UI刷新;本组件私有。
- @Prop:父传子,单向只读,子不能直接修改;
- @Link:父传子,双向绑定,父子同步;
- @ObjectLink:复杂对象/数组双向绑定(引用类型);
- @Watch:监听状态变化,触发回调;
- @Track:只监听对象指定属性,细粒度更新,减少无效渲染。
示例:@State + @Link
@Entry
@Component
struct Parent {
@State count: number = 0;
build() {
Column() {
Text(`父组件count:${this.count}`)
// @Link双向绑定,子修改同步父
Child({childCount: $count})
}
}
}
@Component
struct Child {
@Link childCount: number
build() {
Button("+1").onClick(()=>{
this.childCount++
})
}
}
3. ArkUI渲染原理:什么是虚拟DOM?ArkUI是否使用虚拟DOM?渲染更新机制。
答案
ArkUI没有虚拟DOM。
原理:声明式UI编译后生成渲染节点(RenderNode),状态变更时,框架对比状态,只更新变化节点,增量渲染。
虚拟DOM是React的方案,JS计算diff;ArkUI在编译期做优化,渲染链路更短。
4. ForEach 和 LazyForEach 区别,使用注意事项,性能坑。
答案
- ForEach:一次性渲染全部列表项,大数据列表会一次性创建所有组件,卡顿、内存高;适合少量数据。
- LazyForEach:懒加载,只渲染视口内可见条目,滑动复用,长列表必用。
注意点:必须实现数据源IDataSource,key必须稳定唯一;key重复会渲染错乱。
示例 LazyForEach
class MyDataSource implements IDataSource {
private list: string[] = []
constructor(arr:string[]){
this.list = arr
}
totalCount(): number {
return this.list.length
}
getData(index: number): string {
return this.list[index]
}
registerDataChangeListener(listener: DataChangeListener): void {}
unregisterDataChangeListener():void {}
}
@Entry
@Component
struct ListDemo {
data: MyDataSource = new MyDataSource(["A","B","C","D"])
build() {
List() {
LazyForEach(this.data, (item:string)=>{
ListItem(){Text(item)}
}, (item:string)=>item) // key生成器,保证唯一
}
}
}
5. 自定义组件生命周期:aboutToAppear、aboutToDisappear触发时机。
答案
- aboutToAppear:组件实例创建完成,build执行之前触发;适合初始化请求、赋值。
- aboutToDisappear:组件销毁前触发,用来释放定时器、监听、订阅,防止内存泄漏。
@Component
struct Demo{
aboutToAppear(){
console.info("组件即将出现")
}
aboutToDisappear(){
console.info("组件即将销毁,清理资源")
}
build(){Text("demo")}
}
6. NavDestination + NavRouter 路由框架,页面栈管理,和老Router的差异。
答案
- NavRouter:路由容器;NavDestination:路由页面节点;维护页面栈,原生支持返回、页面参数、栈操作。
- 老Router:API8及之前,Router.push,无统一页面栈管理,参数传递能力弱,官方推荐迁移NavDestination。
7. NavDestination 页面传参有哪几种方式,页面栈如何清除、拦截返回。
答案
传参方式:
- NavRouteInfo携带params参数;
- AppStorage全局状态;
页面栈操作:pop()出栈,clear()清空栈;onBackPress拦截返回事件。
示例:页面跳转传参
@Entry
@Component
struct NavRootPage {
@State pathStack: NavPathStack = new NavPathStack()
build() {
NavRouter(this.pathStack) {
NavDestination() {
Button("跳转详情页").onClick(()=>{
// 跳转并传参
this.pathStack.pushPath({name:"Detail",param:{id:100,name:"测试"}})
})
}.name("Home")
NavDestination() {
DetailPage()
}.name("Detail")
}
}
}
@Component
struct DetailPage {
@State params:any = null
onReady(context: NavDestinationContext) {
this.params = context.pathInfo.param
hilog.info(0x001, "nav", `接收参数:${JSON.stringify(this.params)}`)
}
build() {
Column(){Text(`id:${this.params?.id}`)}
}
}
8. 组件复用:reuse,复用组件的生命周期。
答案
reuse开启组件复用,组件从缓存池中取出,不销毁重建;
生命周期:aboutToReuse(复用时触发),aboutToRecycle(回收缓存),不会走aboutToDisappear。适合长列表组件复用。
9. 布局原理:Flex、Column、Row、Stack,约束优先级(measure/layout流程)
答案
- Measure阶段:父给子宽高约束,子测量自身需要尺寸;
- Layout阶段:父确定子位置。
- Row:水平线性布局;Column:垂直线性布局;Flex弹性;Stack堆叠(z轴)。
约束优先级:组件width/height > layoutWeight > 内容自适应。
10. 动画:属性动画、显式动画、转场动画,animateTo使用注意点。
答案
- 属性动画:组件属性animation,自动动画;
- animateTo:显式动画,代码触发状态变更产生动画;
- 页面转场:页面切换动画。
注意:animateTo内部修改@State变量;动画只能驱动可动画属性。
@Entry
@Component
struct AnimDemo {
@State w:number = 100
build() {
Column(){
Button("动画")
.onClick(()=>{
animateTo({duration:500},()=>{
this.w = 200
})
})
Rect().width(this.w).height(100).fill(Color.Red)
}
}
}
11. 弹窗:AlertDialog、CustomDialog,自定义Dialog踩坑点。
答案
AlertDialog系统预置弹窗;CustomDialog自定义弹窗。
踩坑:弹窗不会跟随页面自动销毁;页面销毁必须关闭dialog,否则内存泄漏;弹窗层级问题。
@CustomDialog
struct MyDialog {
controller: CustomDialogController
build() {
Column(){
Text("自定义弹窗")
Button("关闭").onClick(()=>this.controller.close())
}
}
}
@Entry
@Component
struct DialogPage {
dialogCtrl: CustomDialogController = new CustomDialogController({builder:MyDialog()})
build() {
Button("打开弹窗").onClick(()=>this.dialogCtrl.open())
}
}
12. 事件分发:触摸事件冒泡、阻止冒泡方式。
答案
触摸事件默认冒泡,子触发后向上传递父组件;使用stopPropagation()停止冒泡。
Column()
.onTouch((e)=>{
console.info("父")
})
{
Text("点击").onTouch((e)=>{
console.info("子")
e.stopPropagation() //阻止冒泡,父不会收到事件
})
}
13. Canvas组件使用场景,离屏渲染怎么实现。
答案
Canvas用于自定义绘制(图表、签名);离屏渲染OffscreenCanvas,不绑定屏幕,后台绘制,提升性能。
三、Stage模型 & UIAbility(重中之重)
1. UIAbility的启动模式(单实例、多实例),怎么配置。
答案
- singleton(单实例,默认):系统只存在一个UIAbility实例,多次拉起复用;
- multiInstance(多实例):每次拉起新建实例,多个页面独立。
配置在module.json5 -> abilities -> launchType。
2. UIAbility之间跳转,传参方式,跨Ability数据传递限制。
答案
使用Want跳转;参数放在want.parameters。
限制:只能传递基础类型,不能传大对象、句柄;大数据建议持久化后传递key。
3. UIAbility前后台切换会触发哪些生命周期,后台切前台数据丢失怎么处理。
答案
切后台onBackground;切前台onForeground。
后台被系统回收时实例销毁;解决方案:onSaveState保存数据到Preferences/RDB,onCreate读取恢复。
4. AbilityStage和UIAbility关系,同一个应用多个UIAbility是否共用一个AbilityStage?
答案
同HAP下所有UIAbility共享同一个AbilityStage;不同HAP有独立AbilityStage。
5. 启动参数want对象详解,want的action、uri、parameters。
答案
Want是跨能力拉起载体:
action:动作标识;uri:资源地址;parameters:参数键值对。
6. 应用冷启动、热启动的定义,冷启动流程。
答案
冷启动:进程不存在,系统新建进程,加载HAP、初始化AbilityStage、UIAbility、渲染页面;速度慢。
热启动:进程存活,UIAbility切后台,重新onForeground,不需要重建进程。
7. 应用退出方式:finish() 和 system.exit(0) 的区别,推荐用哪个。
答案
- finish():关闭当前UIAbility,由系统管理生命周期,推荐;
- system.exit(0):直接杀死进程,强制退出,跳过生命周期,资源无法释放,不推荐。
8. 什么是ExtensionAbility?列举常用ExtensionAbility类型。
答案
无UI扩展能力,系统回调驱动;ServiceExtensionAbility、FormExtensionAbility卡片、WorkSchedulerExtensionAbility定时任务。
9. 后台限制:鸿蒙应用后台能力,后台任务怎么申请(延时任务、传输任务)
答案
系统严格限制后台常驻;长时间任务要申请后台任务(延时任务、网络传输任务),需要权限,超时系统会终止。
10. 进程模型:一个HAP可以有几个进程?多Ability是否在同一进程。
答案
一个HAP默认单进程;同HAP内所有UIAbility在同一个进程;可配置多进程(极少场景)。
四、数据持久化
1. Preferences 特点、适用场景,局限性。
答案
轻量键值存储,类似SharedPreferences;适合简单配置、开关;
局限:不适合大量数据、复杂查询、大对象;全量加载进内存。
import preferences from '@ohos.data.preferences';
async function prefsDemo(ctx:UIAbilityContext){
let prefs = await preferences.getPreferences(ctx,"my_store")
await prefs.put("name","zhangsan")
await prefs.flush() //落盘
let val = await prefs.get("name","")
}
2. RDB关系型数据库,使用步骤,RDB的增删改查,事务。
答案
RDB是sqlite封装,适合大量结构化数据,支持sql、事务。
步骤:1.获取RdbStore;2.建表;3.增删改查;4.关闭ResultSet。
import relationalStore from '@ohos.data.relationalStore';
async function rdbDemo(ctx:UIAbilityContext) {
const config:relationalStore.RdbStoreConfig = {
name:"test.db",
securityLevel:relationalStore.SecurityLevel.S1
}
// 创建数据库
let store = await relationalStore.getRdbStore(config,1)
//建表
await store.executeSql(`CREATE TABLE IF NOT EXISTS user(id INTEGER PRIMARY KEY AUTOINCREMENT,name TEXT)`)
//插入
await store.insert("user",{name:"张三"})
//查询
let resultSet = await store.query("user",["id","name"])
while(resultSet.goToNextRow()){
console.info(resultSet.getString(1))
}
resultSet.close() //必须关闭,防止内存泄漏
}
3. RDB 游标ResultSet使用注意点,内存泄漏场景。
答案
ResultSet用完必须close();忘记关闭游标会造成数据库句柄泄漏。
4. 三种持久化方案对比:Preferences / RDB / 文件读写。
答案
- Preferences:轻量K-V,小配置;
- RDB:结构化大量数据,支持SQL;
- 文件读写:二进制/文本大文件,图片、文档。
5. 应用沙箱文件目录,如何获取沙箱路径,能否直接写绝对路径。
答案
通过context获取filesDir/cacheDir;禁止硬编码绝对路径,不同设备路径不同。
6. 跨HAP之间数据共享怎么做。
答案
- 统一RDB放在entry模块;
- 使用公共HSP封装数据库能力;
- 分布式数据管理。
7. 大文件存储方案,图片缓存放在哪个目录。
答案
图片缓存放cacheDir,系统可自动清理;大文件二进制使用fs读写。
五、工程构建 hvigor & 工程配置
1. hvigor是什么,hvigor和hvigor-ohos-plugin作用。
答案
hvigor是鸿蒙构建工具,替代旧的gradle;hvigor-ohos-plugin是鸿蒙构建插件,负责编译ArkTS、打包HAP。
2. module.json5 核心字段含义。
答案
模块配置文件:模块名称、abilities、权限、页面入口、元服务配置。
3. build-profile.json5 作用,编译选项配置。
答案
工程构建配置:签名、编译参数、产品配置、target。
4. HAP打包,debug/release包差异。
答案
debug:调试符号、日志、预览支持;release:代码压缩、去除调试信息,签名发布包。
5. 模块依赖:本地模块、HAR、HSP的区别。
答案
- HAR:静态共享包,编译时代码拷贝到依赖方;版本固化;适合公共组件。
- HSP:动态共享包,运行时加载,多HAP复用同一份代码;适合大公共业务模块。
6. HAR 和 HSP:静态共享包 vs 动态共享包,适用场景,版本依赖。
答案
HAR:静态,打包复制代码,简单组件库;HSP动态,运行时共享,减小包体积,多HAP项目。
7. 编译时报错:预览器白屏,排查思路。
答案
- 代码语法错误;
- @Entry页面缺失;
- 状态初始化异常;
- 资源路径错误;
- 版本/API不匹配。
8. 资源限定符(color、string、media)资源匹配规则。
答案
资源目录加限定词(zh_CN、dark),系统按设备语言、深浅色、分辨率自动匹配资源。
9. 多语言适配怎么实现。
答案
新建不同语言string.json资源,$r(“app.string.xxx”)引用,系统自动跟随设备语言。
10. 版本管理、签名配置,调试签名/发布签名。
答案
调试签名:DevEco自动生成,仅本机调试;发布签名:应用市场需要正式证书,打包AppPack。
六、性能优化(面试必问)
1. 鸿蒙应用卡顿排查思路,HiProfiler工具使用。
答案
HiProfiler性能分析工具,查看FPS、CPU、内存。排查步骤:
- 看FPS是否低于60;
- 定位主线程耗时函数;
- 查看UI渲染耗时;
- 定位频繁状态刷新、长列表、大图片。
2. UI渲染卡顿常见原因,如何定位。
答案
主线程阻塞(大量同步计算)、@State频繁更新、ForEach渲染大量节点、大图解码。
定位:HiProfiler、HiLog打点。
3. LazyForEach优化列表,避免列表卡顿的手段。
答案
使用LazyForEach代替ForEach;固定item高度;图片异步加载;减少item内部@State。
4. @State滥用带来的性能问题,状态最小化原则。
答案
@State变更会触发组件重建;不必要变量不要加@State;状态范围尽量缩小,只绑定需要刷新UI的数据。
5. 内存泄漏常见场景:定时器、事件监听、RDB游标、自定义组件。
答案
- setInterval定时器在aboutToDisappear未清除;
- 事件订阅没有取消监听;
- ResultSet游标忘记close;
- 全局持有组件实例引用,组件无法回收。
6. 图片优化:图片格式、尺寸、异步加载、缓存。
答案
使用webp减小体积;图片尺寸适配控件大小;使用AsyncImage;缓存放cacheDir。
7. 包体积优化方案。
答案
图片压缩、资源裁剪、HAR抽公共代码、移除无用资源、混淆、分包feature HAP。
8. 冷启动慢如何排查和优化。
答案
排查:HiProfiler看启动链路耗时;
优化:onCreate减少同步任务,延迟非必要初始化,懒加载页面资源。
9. 后台耗电优化,频繁唤醒问题。
答案
减少定时器轮询;优先系统回调任务;非实时逻辑批量处理。
10. 如何监测页面FPS。
答案
HiProfiler;开发者选项开启FPS悬浮窗。
七、分布式能力(中高级)
1. 分布式软总线是什么。
答案
跨设备通信底座,自动发现设备、组网,屏蔽不同设备通信差异。
2. 分布式数据管理(DistributedData)适用场景。
答案
多设备之间数据同步,同一账号下多端数据自动同步。
3. 分布式设备发现,跨设备拉起应用。
答案
通过软总线发现在线设备,使用Want指定deviceId拉起远端UIAbility。
4. 跨设备迁移:UIAbility迁移,迁移的限制。
答案
将当前页面迁移到另一设备;限制:两端应用版本一致,支持迁移权限,网络良好。
备注:普通应用岗问的浅,架构/分布式岗位深挖。
八、进阶架构 & 工程实践
1. 鸿蒙应用分层架构设计(推荐:UI层、业务层、数据层)
答案
三层架构:
- UI层:ArkUI页面、组件,只负责展示,不写业务;
- 业务层(ViewModel/Service):业务逻辑,状态转换;
- 数据层:数据库、网络请求、本地存储。
依赖方向:UI依赖业务层;业务层依赖数据层;单向依赖。
2. 如何在ArkTS实现MVVM,数据和UI解耦。
答案
ViewModel使用LocalStorage/AppStorage存放状态;UI监听状态,业务逻辑放在ViewModel,UI不处理业务。
3. 全局状态管理方案:AppStorage、LocalStorage,适用场景。
答案
- LocalStorage:页面/组件树内局部全局;
- AppStorage:整个应用全局状态。
4. AppStorage和LocalStorage区别,全局状态踩坑。
答案
AppStorage全局,生命周期跟随应用;LocalStorage绑定页面节点树;
踩坑:AppStorage大量数据不及时清理,内存持续占用。
5. 模块化拆分:业务模块抽HAR/HSP的边界怎么划分。
答案
通用基础组件、工具类抽HAR;大型公共业务模块,多HAP共享,抽HSP。业务模块按业务域拆分feature HAP。
6. 组件库封装思路,公共组件设计原则。
答案
单一职责;参数化配置;@BuilderParam插槽;对外最小暴露属性;事件回调解耦。
7. 埋点设计,HiLog封装。
答案
封装统一埋点服务,区分开发日志和业务埋点;生产环境关闭debug日志。
8. 异常捕获:全局异常捕获,JS崩溃捕获。
答案
UIAbility中注册应用全局错误监听,捕获JS异常,上报埋点。
9. 单元测试:hvigor单元测试,ArkUI组件测试。
答案
hvigor支持测试框架,对service、工具类写单元测试;组件测试使用ArkUI测试框架。
10. 灰度发布、应用市场上架流程。
答案
应用市场上传AppPack;配置灰度,分批次放量;审核后正式发布。
九、手写代码题(现场编码)
上面章节已经附带基础示例,这里汇总完整可运行代码片段
十、场景综合问答题(开放式,架构岗重点)
1. 用户反馈页面切换卡顿,你的排查步骤?
答案
- 复现问题,HiProfiler抓性能数据;
- 看主线程CPU,是否有大量同步计算;
- 查看页面节点数量,是否滥用ForEach;
- 检查@State范围,是否频繁刷新大量组件;
- 图片是否大图未压缩;
- 定位到代码后优化,替换LazyForEach、异步加载。
2. 项目越来越大,模块耦合严重,怎么重构?
答案
- 分层,UI/业务/数据解耦;
- 公共能力抽HAR/HSP;
- 消除跨模块直接import,使用接口;
- 按业务拆feature HAP;
- 全局状态收敛,减少跨页面直接依赖。
3. 应用后台被系统杀掉,如何保存现场,恢复页面状态?
答案
UIAbility的onSaveState,将页面状态存入RDB/Preferences;onCreate读取保存的状态,恢复页面数据。
4. 多HAP项目,公共业务如何复用,HAR还是HSP?
答案
基础组件、工具类:HAR;大业务模块,多个HAP同时引用,需要减少包体积:HSP。
5. 页面大量图片列表,滑动出现闪烁、内存飙升怎么处理?
答案
- LazyForEach;
- AsyncImage异步加载,设置合适宽高;
- 图片压缩;
- 图片缓存;
- 页面销毁释放图片资源。
6. 预览器白屏,从哪些方向排查?
答案
- @Entry页面语法报错;
- 导入模块不存在;
- 变量初始化异常,渲染时报错;
- API版本不匹配;
- 资源引用路径错误。
7. 敏感权限动态申请完整流程,如果用户拒绝权限怎么降级。
答案
- module.json5声明权限;
- 代码调用requestPermissions;
- 获取授权结果;
- 拒绝时,禁用相关功能,友好提示,引导用户去设置页手动开启权限。
8. 原子化服务开发和普通应用差异,需要注意什么。
答案
免安装,包大小限制严格;无桌面图标;生命周期由系统严格管控,不能后台长时间运行;元服务入口配置,支持卡片拉起。
十一、反问面试官(面试结尾用)
- 团队使用API哪个版本,Stage模型全面落地了吗?
- 项目是原生ArkTS还是跨端(uni-app等)?
- 项目组件库是自研还是官方组件扩展?
- 是否有分布式/原子化服务相关业务?
精简版|10道高频突击题(面试前速刷,带简答)
- Stage和FA区别
答:FA老模型;Stage拆分UIAbility/ExtensionAbility,支持多HAP、元服务,推荐使用。 - 状态装饰器@State/@Link/@Prop/@ObjectLink区别
答:@State内部状态;@Prop单向子只读;@Link双向简单类型;@ObjectLink复杂对象双向绑定。 - NavDestination路由使用和页面栈
答:NavRouter容器,NavDestination页面;NavPathStack管理页面栈,push/pop。 - LazyForEach和ForEach区别
答:ForEach一次性渲染全部;LazyForEach视口懒加载,长列表用。 - HAR和HSP
答:HAR静态包,编译拷贝;HSP动态共享包,运行时复用。 - RDB和Preferences对比
答:Preferences轻量K-V;RDB数据库,适合大量结构化数据,支持SQL事务。 - UIAbility生命周期,前后台切换
答:onCreate创建;onForeground前台;onBackground后台;onDestroy销毁。 - 应用冷启动优化手段
答:主线程减少同步任务,延迟初始化,懒加载资源。 - 内存泄漏常见场景
答:定时器未清理、事件监听未取消、RDB游标不close、全局持有组件引用。 - AppStorage和LocalStorage
答:AppStorage应用全局;LocalStorage组件树局部状态。
我可以再帮你拆分2种版本:
- 【纯题目版】(用于面试考官)
- 【题库+答案分离版】题目一页,参考答案单独一页(适合笔试自测)
你想要拆分吗?或者我再补充一套鸿蒙架构主观大题?
更多推荐




所有评论(0)