注意:博主有个鸿蒙专栏,里面从上到下有关于鸿蒙next的教学文档,大家感兴趣可以学习下
如果大家觉得博主文章写的好的话,可以点下关注,博主会一直更新鸿蒙next相关知识
专栏地址: https://blog.csdn.net/qq_56760790/category_12794123.html
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 如何进行数据持久化?
- 用户首选项(Preferences):这是一种轻量级的配置数据持久化方式,适用于保存应用配置信息、用户偏好设置等。它通过文本形式保存数据,并且数据会全量加载到内存中,因此访问速度快,但不适合存储大量数据。
- 键值型数据库(KV-Store):适用于存储结构简单的数据,如商品名称和价格、员工工号和出勤状态等。键值型数据库以“键值对”的形式组织数据,适合数据关系不复杂的场景。
- 关系型数据库(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 自定义组件的创建和渲染流程
- 自定义组件的创建:自定义组件的实例由ArkUI框架创建。
- 初始化自定义组件的成员变量:通过本地默认值或者构造方法传递参数来初始化自定义组件的成员变量,初始化顺序为成员变量的定义顺序。
- 如果开发者定义了aboutToAppear,则执行aboutToAppear方法。
- 在首次渲染的时候,执行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 如何设置沉浸式效果
- 使用windowStage的设置全屏的方式
- 使用组件的安全区域扩展的方式
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通信有大概两种方式
- 通过消息机制推送,类似于前端的postMessage的跨域通信,首先通过原生端的webviewController进行创建通信端口, createMessagePorts, 该方法会创建两个端口,一个用作原生端,一个用作h5端,然后通过webviewController将其中一个端口通过postMessage发送到h5端,h5端用onmessage来接收该端口,并全局缓存,此时,h5端用接收的端口发送消息给原生端,原声端用自己剩余的端口进行onMessage接听消息,此时就可以实现双向通信
- 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-跳转到登页