写点什么

鸿蒙 NEXT 开发 - 面试题库

作者:东林知识库
  • 2025-03-31
    江苏
  • 本文字数:8380 字

    阅读完需:约 27 分钟

1. 简历模板

鸿蒙 next 出来的时间没那么长,企业接受能力也基本不是要求纯鸿蒙开发的,一般正常是安卓+鸿蒙或者前端+鸿蒙或者 Java+鸿蒙,大家最好不要单独写鸿蒙技能,容易简历被筛选掉


示例


  • 精通 Html+CSS+JAVASCRIPT 的前端布局,开发语言及样式处理

  • 精通 Vue2+Vue3/TS + 小程序 + React 及各类组件库的应用与开发

  • 鸿蒙-熟练掌握 ArkTS/ArkUI/主流能力 Kit 及 HarmonyOS 应用开发

  • 鸿蒙-掌握各类装饰器/State/Prop/Link/Provide/Consume/StorageLink/Observed/ObjectLink 的用法

  • 鸿蒙-掌握 Builder/BuilderParams 尾随必报-Styles/Extend 公共样式处理

  • 鸿蒙-掌握 ArkUI 自定义组件的封装-传值-及各层级组件传值

  • 鸿蒙-ability 的启动,运行,传值的各类方式及路由传值的各种方式

  • 鸿蒙-掌握原生能力如 动画/PCM 录音/PCM 播音/语音转化/拍照/视频/及图片压缩/解压缩相关能力

  • 鸿蒙-掌握多线程 TaskPool 及 Worker 的用法,掌握线程通信-emiiter/eventHub/commonEventManager 的用法

  • 还可以加+... API 文档中 随便抓几个 KIt 的能力,加上去

2. 面试题

2.1 鸿蒙和安卓和 IOS 的区别

HarmonyOS 是华为开发的一个开源、分布式的操作系统。它设计用于多种设备,包括智能手机、平板电脑、智能电视和物联网设备。与 Android 和 iOS 的主要区别在于:


  • 分布式架构:HarmonyOS 支持跨设备无缝协作,允许设备之间共享硬件资源。

  • 性能:HarmonyOS 优化了任务调度和内存管理,提高了性能和响应速度。

  • 安全性:HarmonyOS 采用了多层次的安全策略,包括数据加密和安全启动。

  • 生态系统:HarmonyOS 正在构建自己的应用生态系统,鼓励开发者使用 Ark Ts 和 ArkUI 框架。

2.2 HarmonyOS 应用打包后的文件扩展名是?

打包后的文件扩展名为.hap(HarmonyOS Ability Package),这是 HarmonyOS 应用的标准包格式

2.3 如何进行数据持久化?

  1. 用户首选项(Preferences):这是一种轻量级的配置数据持久化方式,适用于保存应用配置信息、用户偏好设置等。它通过文本形式保存数据,并且数据会全量加载到内存中,因此访问速度快,但不适合存储大量数据。

  2. 键值型数据库(KV-Store):适用于存储结构简单的数据,如商品名称和价格、员工工号和出勤状态等。键值型数据库以“键值对”的形式组织数据,适合数据关系不复杂的场景。

  3. 关系型数据库(RelationalStore):基于 SQLite,适用于存储包含复杂关系的数据,如学生信息、雇员信息等。关系型数据库提供了一系列 SQL 操作,如增删改查等。

2.4 鸿蒙简单介绍和发展历程

HarmonyOS 是新一代的智能终端操作系统,为不同设备的智能化、互联与协同提供了统一的语言。带来简洁,流畅,连续,安全可靠的全场景交互体验。


鸿蒙操作系统发展历程


  • 2019 年 8 月 9 日 鸿蒙 1.0 发布,首次应用于华为荣耀智慧屏产品中,标志着华为正式进军操作系统领域

  • 2020 年 9 月 10 日 鸿蒙 2.0 在华为开发者大会上发布,适用于部分手机、车机、智能电视等设备

  • 2022 年 7 月 27 日 鸿蒙 3.0 在 HarmonyOS3 及华为全场景新品发布会上正式发布,支持更多设备加入超级终端,并提升了鸿蒙智联、万能卡片、流畅性能、隐私安全、信息无障碍等方面

  • 2023 年 8 月 4 日 鸿蒙 4.0 在华为开发者大会上正式发布,提供了强大的智能互联能力,并在多屏跨设备投屏等方面实现突破

  • 2024 年 1 月 18 日 鸿蒙 Next 开发者预览版本发布,将不在兼容安卓应用

2.5 鸿蒙使用网络资源的时候,需要申请什么权限

使用网络资源时,需要申请权限 ohos.permission.INTERNET


在 module.json5 文件中加上(也就是在 module 下面加上 requestPermissions)


{  "module": {    "name": "entry",    "type": "entry",    "description": "$string:module_desc",    "mainElement": "EntryAbility",    "deviceTypes": [      "phone",      "tablet",      "2in1"    ],    "requestPermissions":[      {        "name" : "ohos.permission.INTERNET",        "reason": "$string:reason",        "usedScene": {          "abilities": [            "FormAbility"          ],          "when":"inuse"        }      }    ],
复制代码


2.6 父子组件如何通信

2.6.1 @Prop 装饰器:父子单向同步

@Prop 装饰的变量可以和父组件建立单向的同步关系。@Prop 装饰的变量是可变的,但是变化不会同步回其父组件。

2.6.2 @Link 装饰器:父子双向同步

子组件中被 @Link 装饰的变量与其父组件中对应的数据源建立双向数据绑定。

2.6.3 @Provide 和 @Consume 装饰器:与后代组件双向同步

@Provide 和 @Consume,应用于与后代组件的双向数据同步,应用于状态数据在多个层级之间传递的场景。


@Provide/@Consume 装饰的状态变量有以下特性:


  • @Provide 装饰的状态变量自动对其所有后代组件可用,即该变量被“provide”给他的后代组件。由此可见,@Provide 的方便之处在于,开发者不需要多次在组件之间传递变量。

  • 后代通过使用 @Consume 去获取 @Provide 提供的变量,建立在 @Provide 和 @Consume 之间的双向数据同步,与 @State/@Link 不同的是,前者可以在多层级的父子组件之间传递。

  • @Provide 和 @Consume 可以通过相同的变量名或者相同的变量别名绑定,建议类型相同,否则会发生类型隐式转换,从而导致应用行为异常。

2.6.4 @Observed 和 @ObjectLink 装饰器:嵌套类对象属性变化

上文所述的装饰器仅能观察到第一层的变化,但是在实际应用开发中,应用会根据开发需要,封装自己的数据模型。对于多层嵌套的情况,比如二维数组,或者数组项 class,或者 class 的属性是 class,他们的第二层的属性变化是无法观察到的。这就引出了 @Observed/@ObjectLink 装饰器。


@ObjectLink 和 @Observed 类装饰器用于在涉及嵌套对象或数组的场景中进行双向数据同步:


  • 被 @Observed 装饰的类,可以被观察到属性的变化;

  • 子组件中 @ObjectLink 装饰器装饰的状态变量用于接收 @Observed 装饰的类的实例,和父组件中对应的状态变量建立双向数据绑定。这个实例可以是数组中的被 @Observed 装饰的项,或者是 class object 中的属性,这个属性同样也需要被 @Observed 装饰。

  • @Observed 用于嵌套类场景中,观察对象类属性变化,要配合自定义组件使用(示例详见嵌套对象),如果要做数据双/单向同步,需要搭配 @ObjectLink 或者 @Prop 使用(示例详见@Prop与@ObjectLink的差异)。

2.7 UIAbility 生命周期

  • onCreate


Ability 创建时回调,执行初始化业务逻辑操作。


  • onDestory


Ability 生命周期回调,在销毁时回调,执行资源清理等操作。


  • onWindowStageCreate


当 WindowStage 创建后调用。


  • onWindowStageDestory


当 WindowStage 销毁后调用。


  • onForeground


Ability 生命周期回调,当应用从后台转到前台时触发。


  • onBackground


Ability 生命周期回调,当应用从前台转到后台时触发

2.8 页面和自定义组件生命周期

在开始之前,我们先明确自定义组件和页面的关系:


  • 自定义组件:@Component 装饰的 UI 单元,可以组合多个系统组件实现 UI 的复用,可以调用组件的生命周期。

  • 页面:即应用的 UI 页面。可以由一个或者多个自定义组件组成,@Entry装饰的自定义组件为页面的入口组件,即页面的根节点,一个页面有且仅能有一个 @Entry。只有被 @Entry 装饰的组件才可以调用页面的生命周期。


页面生命周期,即被 @Entry 装饰的组件生命周期,提供以下生命周期接口:


  • onPageShow:页面每次显示时触发一次,包括路由过程、应用进入前台等场景。

  • onPageHide:页面每次隐藏时触发一次,包括路由过程、应用进入后台等场景。

  • onBackPress:当用户点击返回按钮时触发。


组件生命周期,即一般用 @Component 装饰的自定义组件的生命周期,提供以下生命周期接口:


  • aboutToAppear:组件即将出现时回调该接口,具体时机为在创建自定义组件的新实例后,在执行其 build()函数之前执行。

  • aboutToDisappear:aboutToDisappear 函数在自定义组件析构销毁之前执行。不允许在 aboutToDisappear 函数中改变状态变量,特别是 @Link 变量的修改可能会导致应用程序行为不稳定。

2.9 自定义组件的创建和渲染流程

  1. 自定义组件的创建:自定义组件的实例由 ArkUI 框架创建。

  2. 初始化自定义组件的成员变量:通过本地默认值或者构造方法传递参数来初始化自定义组件的成员变量,初始化顺序为成员变量的定义顺序。

  3. 如果开发者定义了 aboutToAppear,则执行 aboutToAppear 方法。

  4. 在首次渲染的时候,执行 build 方法渲染系统组件,如果子组件为自定义组件,则创建自定义组件的实例。在首次渲染的过程中,框架会记录状态变量和组件的映射关系,当状态变量改变时,驱动其相关的组件刷新。


当应用在后台启动时,此时应用进程并没有销毁,所以仅需要执行 onPageShow。

2.10 UiAbility 页面启动的方式有哪些?

单例/多例

2.11 常用的修饰符有哪些介绍一下

  • Entry- 修饰成为页面

  • Component -修饰成为组件

  • Preview - 让组件可预览

  • State - 在组件内部定义响应式数据- 必须给初始值

  • Prop- 接收父组件的响应式数据- 可以给初始值 也可以不给

  • Builder- 声明轻量复用 UI

  • BuilderParam - 接收传入的轻量复用 UI- 可以给初始值 也可以不给(如果不给的话,调用时需要判断)

  • CustomDialog- 修饰自定义弹层

  • Styles- 修饰样式复用集合-不允许传参数

  • Extend- 修饰某个特定组件的样式复用集合- 允许传参数

  • Link- 可以实现父-子的双向绑定- 注意: $$同样可以实现和 Link 绑定**(必须不能给初始值)**

  • LocalStorageProp 单向读取 LocalStorage 共享的属性**(必须给初始值)**

  • LocalStorageLink 。双向读取 LocalStorage 共享的属性 必须给初始值)

2.12 页面栈最大容量是多少

页面栈的最大容量是 32 个页面

2.13 路由模式有几种

路由提供了两种不同的跳转模式


1、Standard:无论之前是否添加过,一直添加到页面栈(默认)


2、Single:如果目标页面已存在,会将已有的最近同 url 页面移到栈顶(看情况使用)

2.14 如何设置沉浸式效果

  1. 使用 windowStage 的设置全屏的方式

  2. 使用组件的安全区域扩展的方式

2.15 兄弟组件如何通信

1、通过公共父组件传递如果两个组件是同一个父组件的子组件,可以通过父组件来传递数据或事件。父组件可以作为中介,将一个子组件的数据或事件传递给另一个子组件。


2、使用全局状态管理使用全局状态管理(如 AppStorage、LocalStorage)来存储共享数据。兄弟组件可以独立地读取和更新这个全局状态,从而实现通信。

2.16 Navigation 组件跳转和 router 跳转有什么区别

1、Navigation:是路由容器组件,适用于模块内和跨模块的路由切换,一次开发,多端部署场景。Router 位于页面栈管理节点 stage 下面,不提供导航容器的概念。2、Navigation 和 Router 都支持跳转传参,但 Router 对象中暂不支持方法变量。3、Navigation:支持清理指定路由,页面栈没有上限,可以无限跳转。Router 不支持清理指定路由且页面栈最大为 32,页面栈到达 32 之后必须清除之后才能继续跳转。4、Navigation:支持自定义转场动画和共享元素转场动画。 Router:仅支持简单自定义转场动画。5、Navigation:支持通过 setInterception 方法设置路由拦截。Router:不支持路由拦截。6、Navigation:支持沉浸式页面和模态嵌套路由。Router:不支持,需要通过窗口配置实现沉浸式页面

2.17 ArkUI 框架有哪些特点

ArkUI 框架是鸿蒙(HarmonyOS)中的一个重要组件框架,具有以下几个特点:


1、组件树结构 : ArkUI 框架通过布局组件和基础组件构建界面描述树(组件树),其中基础组件为叶子节点,布局组件为中间节点 。当用户进行交互时,会触发界面修改,通过重新渲染组件树来实现应用界面更新 。


2、数据与 UI 更新过程 : ArkUI 框架的数据处理过程和 UI 更新过程是分开进行的。数据处理过程中,主要是对状态数据进行更新,并通过标脏过程确定布局最小影响范围,减少不必要的重新布局 。UI 更新过程包括组件标脏、布局、测量和渲染等阶段 。


3、布局组件 : ArkUI 框架提供了多种布局组件,如 Row、Column、Stack、Flex、List、Grid、RelativeContainer 等。开发者可以根据场景选择合适的布局组件,以优化性能 。例如,线性布局(Row、Column)适用于横向或纵向排列组件,而弹性布局(Flex)适用于需要弹性排列的场景。


4、性能优化 : ArkUI 框架在性能优化方面做了很多工作。例如,通过减少不必要的组件嵌套和节点数量,降低布局测算的复杂度,从而提升性能。开发者可以使用 DevEco Studio 提供的工具(如 Profiler 和 ArkUI Inspector)来查看性能瓶颈和组件树结构,进一步优化应用性能。


5、状态管理 : ArkUI 框架支持状态管理最佳实践,通过有效的状态管理减少无效的 UI 更新操作,提升性能。例如,在状态变量变化导致 UI 更新时,只更新部分组件,而不是重新渲染整个界面。

2.18 跨设备通信的方式有哪些

HarmonyOS 支持多种跨设备通信方式,包括:


  • 分布式软总线:一种高性能的通信机制,允许设备之间建立直接连接,进行数据传输。

  • 蓝牙:使用标准的蓝牙技术进行设备间的通信。

  • WLAN:通过 WLAN 网络实现设备间的通信。

  • 远程服务调用:通过分布式任务调度实现跨设备的服务调用。

2.19 HarmonyOS 中的权限管理模型是怎样的

  • 权限声明:应用在 config.json 中声明所需的权限。

  • 权限申请:在应用运行时,根据需要动态申请权限。

  • 权限检查:在执行敏感操作前,检查是否已获得相应权限。

  • 权限分组:系统将权限分为不同的组,便于管理和申请。

2.20 ArkTS 基本介绍

ArkTS 是 HarmonyOS 优选的主力应用开发语言。


ArkTS 围绕应用开发在 TypeScript(简称 TS)生态基础上做了进一步扩展,保持了 TS 的基本风格,同时通过规范定义强化开发期静态检查和分析,提升程序执行稳定性和性能。


从 API version 10 开始,ArkTS 进一步通过规范强化静态检查和分析,对比标准 TS 的差异可以参考从 TypeScript 到 ArkTS 的适配规则:


  • 强制使用静态类型:静态类型是 ArkTS 最重要的特性之一。如果使用静态类型,那么程序中变量的类型就是确定的。同时,由于所有类型在程序实际运行前都是已知的,编译器可以验证代码的正确性,从而减少运行时的类型检查,有助于性能提升。

  • 禁止在运行时改变对象布局:为实现最大性能,ArkTS 要求在程序执行期间不能更改对象布局。

  • 限制运算符语义:为获得更好的性能并鼓励开发者编写更清晰的代码,ArkTS 限制了一些运算符的语义。比如,一元加法运算符只能作用于数字,不能用于其他类型的变量。

  • 不支持 Structural typing:对 Structural typing 的支持需要在语言、编译器和运行时进行大量的考虑和仔细的实现,当前 ArkTS 不支持该特性。根据实际场景的需求和反馈,我们后续会重新考虑。


ArkTS 它是纯新的一门语言,它不是前端也不是 TypeScript,它是 TS 的超集


2.21 模块如何导出导入的

程序可划分为多组编译单元或模块。


每个模块都有其自己的作用域,即,在模块中创建的任何声明(变量、函数、类等)在该模块之外都不可见,除非它们被显式导出。


与此相对,从另一个模块导出的变量、函数、类、接口等必须首先导入到模块中。


导出


可以使用关键字 export 导出顶层的声明。


导入


可以使用关键字 import 导入

2.22 说一下你做的这个项目,开发鸿蒙项目的流程是什么

  • 创建项目

  • 导入一些资源/色值

  • 创建一些公共目录-组件库-数据模型-工具类-请求-常量

  • 读写首选项工具类

  • 封装请求工具类

  • 使用泛行工具统一处理响应数据

  • 封装组件库-列表-加载-上传-日历-弹出时间-卡片。。。

  • 分包

  • 发布上线

2.23 鸿蒙的系统能力你用过哪些,简单讲一下

  • 弹窗

  • 路由跳转

  • 声音播放-av-player(Video)

  • 震动

  • 打电话

  • 定位(需要用户授权)

  • 发布通知

  • ability 通信-传参

  • 网络权限

  • 首选项

  • 文件选择

  • 后台订阅闹铃

2.24 你项目中的权限是如何管理的

  • 进入应用-判断 token(坑点-只能用首选项获取 token)- 跳转到主页/登录页

  • 销毁应用

  • 进入登录页- 获取 token(存储到持久化/首选项)-跳到主页

  • token 超时- 销毁 token(销毁持久化/首选项)-跳回登录页

2.24 H5 和原生是怎么通信的

鸿蒙原生和 h5 通信有大概两种方式


  1. 通过消息机制推送,类似于前端的 postMessage 的跨域通信,首先通过原生端的 webviewController 进行创建通信端口, createMessagePorts, 该方法会创建两个端口,一个用作原生端,一个用作 h5 端,然后通过 webviewController 将其中一个端口通过 postMessage 发送到 h5 端,h5 端用 onmessage 来接收该端口,并全局缓存,此时,h5 端用接收的端口发送消息给原生端,原声端用自己剩余的端口进行 onMessage 接听消息,此时就可以实现双向通信

  2. api 调用的形式


原生端可以通过 javascriptProxy 给 h5 页面注入可用的 sdk 应用方法集合,在 h5 完成初始化后,可以直接调用原生的方法,这是 h5 调用原生


原生端也可以直接调用 h5 端的方法 runJavascript,在这个方法里面传入方法调用传参数就可以


需要注意的点: 如果原生端的 sdk 方法是个异步方法,在 h5 端无法及时得到结果,此时需要再用原生反调 h5 进行传递结果

2.26 鸿蒙云服务和微信小程序的区别是什么

本质上很像,因为他们都遵循即用即走的模式,都可以免安装,轻量级的使用。


但是微信小程序本质上是在微信的安卓架构/ios 架构上做了一层代码框架的机制,也就是说本质上- 微信使用安卓/ios 的开发语言完成,小程序是微信自创的一套小程序的开发语言-类似于 Vue 的 MVVM 的框架,然后微信进行了统一的代码编译和代码解释,最终实现如今的小程序的效果


鸿蒙的元服务实现了代码大一统的效果,也就是开发一个鸿蒙应用和鸿蒙元服务本质上都直接使用鸿蒙的 arkTS 和 arkUI 来进行,调用通用能力和 api 方式一致,并且把应用变成元服务变得非常简单,只需要加个参数即可

2.27 鸿蒙的刷新机制是怎么样的,多层嵌套时,是从 build 开始刷新吗

一个组件的渲染- aboutToAppear - build 函数(构建 UI 视图)


当响应式数据发生变化 =》 builde 的重新执行


所有的鸿蒙的响应式监测都只能监测到一层


多层嵌套时-执行的顺序 。洋葱圈模式- 一定时先最里面的组件渲染完毕,一定是最外层的组件最后渲染。


关于更新机制的问题


比较机制- 列表比较-ForEach-有三个参数, 第三个参数需要返回一个唯一的 key, 如果不写,系统会自动帮我们生成一个函数 规则 index_JSON.stringfy(item) { a: 1, b: 2 } => { a: 2: b: 2 }


如果列表中 key 发生变化,更新机制直接销毁该组件,然后重新创建, 但是反之,你给的 key 如果没有发生变化,但是数据变化了,就会出现页面不更新现象。

2.28 说一下全局存储状态用哪些方式

  • LocalStorage- 内存化存储- 局部可用

  • AppStorage- 内存化存储- 全局可用

  • PersitentStoreage- 写入磁盘(沙箱) 全局可用

  • 首选项- 写入磁盘- 全局可用

  • 关系型数据库- 写入磁盘

2.29 你在项目中用过线程通信吗,线程是怎么进行通信的?

emitter 和 eventHub


都是基于事件总线的


区别是:


eventHub 当前线程内通信


emitter 是同一进程不同线程或者同一进程和同一线程也可以通信

2.30 你在项目中使用首选项主要用来做什么

存任何持久化的东西都可以,比如 token,用户信息等。


首选项有长度限制 每一项的长度 8192 个字节

2.31 组件通信的方式有哪些

父传子


子传父


跨层


跨 ability


跨页面

2.32 弹窗 UI 是怎么在页面 UI 中使用的

CustomtDialogController


创建子窗口的形式创建弹层


弹层


bindSheet 半层


bindContentCover 全层

2.33 Builder 和 BuilderParams 的区别

Builder 是当前组件的 UI 复用结构


BuilderParams 是接收父组件传入的 UI 复用结构, 传过来的类型是 UI 复用结构类型


Builder 传值 想要响应式必须是对象,如果基础数据类型,不具备响应式

2.34 对于一些公共的样式你是怎么做的?有没有什么优化的方式

  • 封装组件

  • 抽提 Builder

  • 抽提 Styles 和 Extends

2.35 共享库之间怎么进行页面跳转

  • import 动态引入共享库的页面

  • 给共享库一个 entry 的 name 属性

  • 使用 pushRouteName

  • 不要忘记导入依赖

2.36 websocker 用过吗?说说你在项目中怎么用的

主要用在发消息和接消息,用于客服模块的消息


用过,和前端用法是一样的


const socket = new WebSocket(url)


socket.on("connect", () => {


})


socket.on("message", () => {


})


socket.on("disconnect", () => {


})


socket.send()

2.37 项目中有用到多线程嘛,具体说一下多线程的作用,如何使用的

用了,因为我们要提高性能。


自定义组件创建完成之后,在 build 函数执行之前,将先执行 aboutToAppear()生命周期回调函数。此时若在该函数中执行耗时操作,将阻塞 UI 渲染,增加 UI 主线程负担。因此,应尽量避免在自定义组件的生命周期内执行高耗时操作。在 aboutToAppear()生命周期函数内建议只做当前组件的初始化逻辑,对于不需要等待结果的高耗时任务,可以使用多线程处理该任务,通过并发的方式避免主线程阻塞;也可以把耗时操作改为异步并发或延后处理,保证主线程优先处理组件绘制逻辑。



worker 帮我们处理图片压缩处理完成之后再去执行其它任务

2.38 什么是鸿蒙应用签名

指纹-就是一堆证明当然项目可被 agc 识别并允许调试到设备的说明文件


p12


csr


ce


p7b

2.39 如何引入本地的 web 页面?

web({ src: $rawfile("index.html"),controller: new weview.WebviewController() })


组件


2.40 @Provide 和 @Consume 的使用中,消费者修改了值,提供者那边会变化吗?

当然会,因为都是双向的


2.41 鸿蒙客户端怎么实现长登陆的;再说说 token 的失效后是如何处理的?

  • token 是登录之后得到的,如果失效应该去换取 token,还应有一个 refreshToken,

  • refreshToken 换取一个新的 token

  • 如果换取成功-替换原有 token-重启发请求

  • 如果换取失败-删除 token-删除 refreshToken-跳转到登页

发布于: 3 小时前阅读数: 9
用户头像

享受当下,享受生活,享受成长乐趣! 2025-02-26 加入

鸿蒙、Java、大数据

评论

发布
暂无评论
鸿蒙NEXT开发-面试题库_东林知识库_InfoQ写作社区