IT评测·应用市场-qidao123.com

标题: 2024最新鸿蒙开发口试题合集(一)-HarmonyOS NEXT Release(API 12 Releas [打印本页]

作者: 光之使者    时间: 2025-1-2 23:06
标题: 2024最新鸿蒙开发口试题合集(一)-HarmonyOS NEXT Release(API 12 Releas
1. HarmonyOS应用打包后的文件扩展名是?

打包后的文件扩展名为.hap(HarmonyOS Ability Package),这是HarmonyOS应用的标准包格式
2. 页面和自定义组件生命周期有哪些?

页面和自定义组件生命周期说明
有@Entry装饰器的@component组件的生命周期

有@Entry装饰器和无@Entry装饰器@Component组件都有的生命周期

3. 怎样进行数据持久化?

应用数据持久化
4. 怎样进行全局状态管理?

应用全局的UI状态存储
1. @Provide+@Consume装饰器

2. AppStorage

3. LocalStorage


5. LocalStorage在应用重启后数据会消散吗?


页面级UI状态存储

因为LocalStorage 是一种用于页面或组件级别的数据存储方式,它允许开发者在页面或组件的生命周期内存储和检索数据。LocalStorage 的数据存储在内存中,因此它的读写速率相对较快。但是,当应用重启后,LocalStorage 中的数据会丢失。
6. 父子组件怎样通信?

 
@Prop装饰器、@Link装饰器、@Provide和@Consume装饰器、@Event装饰器、@Parame装饰器、@Provider装饰器和@Consumer装饰器
当前(API 12)状态管理有两个版本 @Component和 @ComponentV2
1. 父子单向数据传递 @State+@Prop
@Prop装饰的变量可以和父组件建立单向的同步关系。@Prop装饰的变量是可变的,但是变革不会同步回其父组件。
2. 父子双向数据传递 @State+@Link 、@objectLink+@Link
子组件中被 @Link装饰的变量与其父组件中对应的数据源建立双向数据绑定。
3. 跨组件通信 @Provide装饰器和 @Consume装饰器
@Provide和 @Consume,应用于与后代组件的双向数据同步,应用于状态数据在多个层级之间传递的场景。不同于 @Prop和 @Link,@Provide和 @Consume摆脱参数传递机制的束缚,实现跨层级传递。
4. @Observed装饰器和 @ObjectLink装饰器
对于多层嵌套的情况,好比二维数组,或者数组项class,或者class的属性是class,他们的第二层的属性变革是无法观察到的。这就要用到 @Observed/@ObjectLink装饰器
   注意ObjectLink装饰器不能在 @Entry装饰的自定义组件中使用且 @ObjectLink 装饰的变量不能被赋值,只能对其属性进行赋值操作
  
7. 兄弟组件怎样通信?



1. 通过公共父组件传递
如果两个组件是同一个父组件的子组件,可以通过父组件来传递数据或事件。父组件可以作为中介,将一个子组件的数据或事件传递给另一个子组件。
2. 使用全局状态管理
使用全局状态管理(如 AppStorage、LocalStorage)来存储共享数据。兄弟组件可以独立地读取和更新这个全局状态,从而实现通信。
8. 怎样实现页面间的通信?

1.使用 @Provide和 @Consume装饰器(见6.3)
2.使用路由跳转传参
  1. import { router } from '@kit.ArkUI';
  2. router.pushUrl({
  3.   url: 'pages/Detail', // 目标url
  4.    params: paramsInfo // 添加params属性,传递自定义参数
  5. })
  6. // 返回指定页面并携带参数
  7. router.back({
  8.   url: 'pages/Home',
  9.   params: {
  10.     info: '来自Home页'
  11.   }
  12. });
复制代码
3.使用导航跳转传参
  1. this.pageStack.pushPath({ name: "PageOne", param: "PageOne Param" })
  2. this.pageStack.pushPathByName("PageOne", "PageOne Param")
复制代码
9. Navigation组件跳转和router跳转有什么区别?


官方文档写了很多,捡几个我觉得比力重要的写的
总而言之,Navigation 组件在功能上更具丰富性和机动性,特别是在处理复杂的导航布局、动效和路由管理方面。
而 Router 则提供了更基础的路由跳转功能,得当简单的路由需求。开发者可以根据应用的详细需求和设计选择最符合的路由方案。
详细的区别如下表:
10. HarmonyOS与Android和iOS有什么区别?


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



Ability是应用/服务所具备的能力的抽象,一个Module可以包含一个或多个 Ability ,在鸿蒙体系中,Ability提供了对 Ability生命周期、上下文情况等调用管理的能力,包括 Ability创建、烧毁、转储客户端信息等
鸿蒙体系中的 Ability重要分为两种范例:UIAbility和 ExtensionAbility。
1. UIAbility :

2. ExtensionAbility :


此外,Ability是Ability模块的基类,提供体系配置更新回调和体系内存调解回调 。Ability的继承关系包括UIAbility和ExtensionAbility等详细类.
总之,Ability是鸿蒙体系中用于管理应用能力的核心组件,通过不同范例的Ability可以实现不同的功能需求。
12. ArkUI框架有哪些特点?

ArkUI框架是鸿蒙(HarmonyOS)中的一个重要组件框架,具有以下几个特点:
13. 跨装备通信的方式有哪些?

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

14. 怎样实现应用的配景运行?


15. Ability是怎样与用户交互的?


16. 怎样实现应用的多语言支持?


17. 分布式数据库是怎样实现数据同步的?


18. 怎样优化应用的性能?


19. HarmonyOS中的权限管理模型是怎样的?


20. LazyForEach是什么?

LazyForEach 是一个用于高效渲染列表的组件或功能,它允许开发者在用户滚动列表时才加载和渲染列表项,而不是一次性渲染整个列表。这种按需渲染的方式可以显著进步应用的性能,特别是在处理大量数据时。
21. LazyForEach的工作原理是什么?

LazyForEach 的工作原理通常是基于用户的滚动位置来动态地创建和烧毁列表项的组件实例。当用户滚动到列表的某个部门时,LazyForEach 会加载并渲染那些即将进入视图的列表项,同时可能会卸载那些滚出视图的列表项,以节省内存和计算资源。
22. Router.replace()方法的作用是什么?和Router.pushUrl()方法有什么区别?

Router.replace()方法用于替换当前路由,并将目标路由压入栈顶。与Router.pushUrl()方法不同,Router.replace()方法不会保存当前路由,而是直接替换掉当前路由。
23. 怎样实现应用的沉浸式模式?

沉浸式模式是指应用界面出现出沉浸式的全屏模式,不留任何体系UI,用户只能看到应用内容。在沉浸式模式下,应用的UI元素会被覆盖,但体系状态栏、导航栏、键盘等体系UI依然可见。以下是实现步骤
1. 设置窗口属性:
在应用的入口Ability中,可以通过设置窗口属性来实现沉浸式模式。这通常涉及到配置窗口特性(Window Features)来隐藏状态栏和导航栏。
2. 使用体系API:
鸿蒙OS提供了API来控制体系UI的显示和隐藏。你可以在应用的代码中调用这些API来实现沉浸式效果。
3. 配置应用的配置文件:
在应用的config.json或其他配置文件中,可以声明应用需要的窗口特性,如ohos:immersive。
4. 动态切换:
应用可以根据用户的交互或特定场景动态地进入或退出沉浸式模式。这可能涉及到监听用户的手势或其他事件来切换UI状态。
5. 适配不同装备:
不同的装备可能有不同的屏幕和体系UI,因此在实现沉浸式模式时,需要考虑不同装备的适配标题。

24. 怎样获取屏幕的安全地区?



示例:
  1. import ohos.aafwk.ability.AbilitySlice;
  2. import ohos.aafwk.content.Intent;
  3. import ohos.agp.window.UIWindow;
  4. import ohos.agp.utils.Rect;
  5. public class MyAbilitySlice extends AbilitySlice {
  6.     @Override
  7.     public void onStart(Intent intent) {
  8.         super.onStart(intent);
  9.         setUIContent(new SurfaceLayout(this));
  10.         UIWindow window = getUIWindow();
  11.         if (window != null) {
  12.             // 获取安全区域
  13.             Rect safeArea = window.getSafeArea();
  14.             // 在这里可以使用safeArea对象,它包含了安全区域的位置和尺寸信息
  15.             // 例如,可以使用safeArea.left, safeArea.top, safeArea.right, safeArea.bottom
  16.         }
  17.     }
  18. }
复制代码
25. ArkTs是什么?

ArkTs介绍
ArkTS是HarmonyOS优选的主力应用开发语言。保持了TypeScript的根本风格,同时通过规范定义强化开发期静态检查和分析,提升步伐实行稳定性和性能。

ArkTS的重要特点包括:


26. ArkTs与TypeScript有什么区别?(答5点以上)


ArkTs官方文档
ArkTS 是基于 TypeScript 开发的框架,但是有一些限定和差异。ArkTS 旨在提供更严格的范例检查和优化的代码性能,同时确保与 HarmonyOS 的开发情况和特性兼容。以下是 ArkTS 与 TypeScript 的差异:


详细区别:
     27. @Provider和@Consumer vs @Provide和@Consume的区别?

@Provider和@Consumer 官方文档
28. @Prop和@ObjectLink装饰器有什么区别?

1.用途

2. 数据传递方式

3. 性能

29. ForEach和LazyForEach的区别?

ForEach和LazyForEach都是用于渲染列表的装饰器,它们的区别在于:

30. UIAbility的生命周期有哪些?

官方文档说明
UIAbility的生命周期包括Create、Foreground、Background、Destroy四个状态
31. H5怎样与HarmonyOS应用(webView)进行通信?官方文档


应用侧可以通过runJavaScript()方法异步调用前端页面的JavaScript相关函数,并通过Promise方式返回脚本实行的效果。runJavaScript需要在loadUrl完成后,好比onPageEnd中调用。

使用Web组件将应用侧代码注册到前端页面中,注册完成之后,前端页面中使用注册的对象名称就可以调用应用侧的函数,实如今前端页面中调用应用侧方法。注册应用侧代码有两种方式,一种在Web组件初始化调用,使用javaScriptProxy()接口。另外一种在Web组件初始化完成后调用,使用registerJavaScriptProxy()接口。
32. 怎样实现图片上传?

有两种方式原生和Web组件:

代码示例:
  1. // pages/xxx.ets
  2. import { common } from '@kit.AbilityKit';
  3. import fs from '@ohos.file.fs';
  4. import { BusinessError, request } from '@kit.BasicServicesKit';
  5. // 获取应用文件路径
  6. let context = getContext(this) as common.UIAbilityContext;
  7. let cacheDir = context.cacheDir;
  8. // 新建一个本地应用文件
  9. let file = fs.openSync(cacheDir + '/test.txt', fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
  10. fs.writeSync(file.fd, 'upload file test');
  11. fs.closeSync(file);
  12. // 上传任务配置项
  13. let header = new Map<Object, string>();
  14. header.set('key1', 'value1');
  15. header.set('key2', 'value2');
  16. let files: Array<request.File> = [
  17. //uri前缀internal://cache 对应cacheDir目录
  18.   { filename: 'test.txt', name: 'test', uri: 'internal://cache/test.txt', type: 'txt' }
  19. ]
  20. let data: Array<request.RequestData> = [{ name: 'name', value: 'value' }];
  21. let uploadConfig: request.UploadConfig = {
  22.   url: 'https://xxx',
  23.   header: header,
  24.   method: 'POST',
  25.   files: files,
  26.   data: data
  27. }
  28. // 将本地应用文件上传至网络服务器
  29. try {
  30.   request.uploadFile(context, uploadConfig)
  31.     .then((uploadTask: request.UploadTask) => {
  32.       uploadTask.on('complete', (taskStates: Array<request.TaskState>) => {
  33.         for (let i = 0; i < taskStates.length; i++) {
  34.           console.info(`upload complete taskState: ${JSON.stringify(taskStates[i])}`);
  35.         }
  36.       });
  37.     })
  38.     .catch((err: BusinessError) => {
  39.       console.error(`Invoke uploadFile failed, code is ${err.code}, message is ${err.message}`);
  40.     })
  41. } catch (error) {
  42.   let err: BusinessError = error as BusinessError;
  43.   console.error(`Invoke uploadFile failed, code is ${err.code}, message is ${err.message}`);
  44. }
复制代码

注意事项
当上传的内容为ArrayBuffer时,用法如下
  1. import axios from '@ohos/axios'
  2. import { FormData } from '@ohos/axios'
  3. import fs from '@ohos.file.fs';
  4. // ArrayBuffer
  5. let formData = new FormData()
  6. let cacheDir = getContext(this).cacheDir
  7. try {
  8.   // 写入
  9.   let path = cacheDir + '/hello.txt';
  10.   let file = fs.openSync(path, fs.OpenMode.CREATE | fs.OpenMode.READ_WRITE)
  11.   fs.writeSync(file.fd, "hello, world"); // 以同步方法将数据写入文件
  12.   fs.fsyncSync(file.fd); // 以同步方法同步文件数据。
  13.   fs.closeSync(file.fd);
  14.   // 读取
  15.   let file2 = fs.openSync(path, 0o2);
  16.   let stat = fs.lstatSync(path);
  17.   let buf2 = new ArrayBuffer(stat.size);
  18.   fs.readSync(file2.fd, buf2); // 以同步方法从流文件读取数据。
  19.   fs.fsyncSync(file2.fd);
  20.   fs.closeSync(file2.fd);
  21.   formData.append('file', buf2);
  22.   // formData.append('file', buf2, { filename: 'text.txt', type: 'text/plain'}); 设置多部分表单数据的数据名称和数据类型类型
  23. } catch (err) {
  24.   console.info('err:' + JSON.stringify(err));
  25. }
  26. // 发送请求
  27. axios.post<string, AxiosResponse<string>, FormData>(this.uploadUrl, formData, {
  28.   headers: { 'Content-Type': 'multipart/form-data' },
  29.   context: getContext(this),
  30.   onUploadProgress: (progressEvent: AxiosProgressEvent): void => {
  31.   console.info(progressEvent && progressEvent.loaded && progressEvent.total ? Math.ceil(progressEvent.loaded / progressEvent.total * 100) + '%' : '0%');
  32. },
  33. }).then((res: AxiosResponse) => {
  34.   console.info("result" + JSON.stringify(res.data));
  35. }).catch((error: AxiosError) => {
  36.   console.error("error:" + JSON.stringify(error));
  37. })
复制代码
当上传的uri时,用法如下
  1. import axios from '@ohos/axios'
  2. import { FormData } from '@ohos/axios'
  3. let formData = new FormData()
  4. formData.append('file', 'internal://cache/blue.jpg')
  5. // formData.append('file', cacheDir + '/hello.txt'); uri支持传入沙箱路径
  6. // 发送请求
  7. axios.post<string, AxiosResponse<string>, FormData>('https://www.xxx.com/upload', formData, {
  8.   headers: { 'Content-Type': 'multipart/form-data' },
  9.   context: getContext(this),
  10.   onUploadProgress: (progressEvent: AxiosProgressEvent): void => {
  11.     console.info(progressEvent && progressEvent.loaded && progressEvent.total ? Math.ceil(progressEvent.loaded / progressEvent.total * 100) + '%' : '0%');
  12.   },
  13. }).then((res: AxiosResponse<string>) => {
  14.   console.info("result" + JSON.stringify(res.data));
  15. }).catch((err: AxiosError) => {
  16.   console.error("error:" + JSON.stringify(err));
  17. })
复制代码
33.hap、har、hsp三者的区别?


34. 鸿蒙常用的装饰器有哪些?


35. 怎样启动一个 ability?

通过 context 对象的 startAbility 方法官方文档:
  1. import { common, Want } from '@kit.AbilityKit';
  2. import { BusinessError } from '@kit.BasicServicesKit';
  3. context = getContext(this) as common.UIAbilityContext; // UIAbilityContext
  4. const want: Want = {
  5.   deviceId: '', // deviceId为空表示本设备
  6.   bundleName: 'com.example.system', // AppScope/app.json5 中找
  7.   abilityName: 'SecondAbility', // 去对应的ability内部找module.json5
  8.   // moduleName: 'entry' // moduleName非必选
  9.   parameters: { // 携带参数
  10.   }
  11. };
  12. this.context.startAbility(want, (err: BusinessError) => {
  13.   if (err.code) {
  14.     // 显式拉起Ability,通过bundleName、abilityName和moduleName可以唯一确定一个Ability
  15.     console.error(`Failed to startAbility. Code: ${err.code}, message: ${err.message}`);
  16.   }
  17. });
复制代码
36. 显示 want 和 隐式 want 的区别?

官方文档

总的来说


37. 三层架构是什么?


官方文档

三层架构为了“一次开发,多端部署”,项目布局接纳三层架构
三层工程布局如下:


38. 优化内存有哪些方法?


官方文档
1. 使用onMemoryLevel监听内存变革
2. 使用LRUCache优化ArkTS内存
比方:我们搜刮租房列表可以无穷加载租房数据,这样数据会越来越多,我们使用LRUCacheUtil来管理数据
3. 使用生命周期管理优化ArkTS内存
比方:aboutToDisappear中烧毁订阅事件,打扫定时器等
4.使用purgeable优化C++内存
39. 多线程实现方式TaskPoll和Worker的区别?

40. 音视频的组件的使用方式?


  1. controller: VideoController = new VideoController()
  2. Video({
  3.   src: $rawfile('test.mp4'),
  4.   previewUri: $r('app.media.startIcon'),
  5.   controller: this.controller
  6. })
  7. .width('100%')
  8. .height(200)
  9. .autoPlay(true)
  10. .controls(true)
复制代码

  1. //配置音频渲染参数并创建AudioRenderer实例,音频渲染参数的详细信息可以查看AudioRendererOptions。
  2. import { audio } from '@kit.AudioKit';
  3. let audioStreamInfo: audio.AudioStreamInfo = {
  4.   samplingRate: audio.AudioSamplingRate.SAMPLE_RATE_48000, // 采样率
  5.   channels: audio.AudioChannel.CHANNEL_2, // 通道
  6.   sampleFormat: audio.AudioSampleFormat.SAMPLE_FORMAT_S16LE, // 采样格式
  7.   encodingType: audio.AudioEncodingType.ENCODING_TYPE_RAW // 编码格式
  8. };
  9. let audioRendererInfo: audio.AudioRendererInfo = {
  10.   usage: audio.StreamUsage.STREAM_USAGE_VOICE_COMMUNICATION,
  11.   rendererFlags: 0
  12. };
  13. let audioRendererOptions: audio.AudioRendererOptions = {
  14.   streamInfo: audioStreamInfo,
  15.   rendererInfo: audioRendererInfo
  16. };
  17. audio.createAudioRenderer(audioRendererOptions, (err, data) => {
  18.   if (err) {
  19.     console.error(`Invoke createAudioRenderer failed, code is ${err.code}, message is ${err.message}`);
  20.     return;
  21.   } else {
  22.     console.info('Invoke createAudioRenderer succeeded.');
  23.     let audioRenderer = data;
  24.   }
  25. });
  26. // 调用on('writeData')方法,订阅监听音频数据写入回调。
  27. import { BusinessError } from '@kit.BasicServicesKit';
  28. import { fileIo } from '@kit.CoreFileKit';
  29. let bufferSize: number = 0;
  30. class Options {
  31.   offset?: number;
  32.   length?: number;
  33. }
  34. let path = getContext().cacheDir;
  35. //确保该路径下存在该资源
  36. let filePath = path + '/StarWars10s-2C-48000-4SW.wav';
  37. let file: fileIo.File = fileIo.openSync(filePath, fileIo.OpenMode.READ_ONLY);
  38. let writeDataCallback = (buffer: ArrayBuffer) => {
  39.   let options: Options = {
  40.     offset: bufferSize,
  41.     length: buffer.byteLength
  42.   }
  43.   fileIo.readSync(file.fd, buffer, options);
  44.   bufferSize += buffer.byteLength;
  45. }
  46. audioRenderer.on('writeData', writeDataCallback);
  47. //调用start()方法进入running状态,开始渲染音频。
  48. import { BusinessError } from '@kit.BasicServicesKit';
  49. audioRenderer.start((err: BusinessError) => {
  50.   if (err) {
  51.     console.error(`Renderer start failed, code is ${err.code}, message is ${err.message}`);
  52.   } else {
  53.     console.info('Renderer start success.');
  54.   }
  55. });
  56. //调用stop()方法停止渲染。
  57. import { BusinessError } from '@kit.BasicServicesKit';
  58. audioRenderer.stop((err: BusinessError) => {
  59.   if (err) {
  60.     console.error(`Renderer stop failed, code is ${err.code}, message is ${err.message}`);
  61.   } else {
  62.     console.info('Renderer stopped.');
  63.   }
  64. });
  65. // 调用release()方法销毁实例,释放资源。
  66. import { BusinessError } from '@kit.BasicServicesKit';
  67. audioRenderer.release((err: BusinessError) => {
  68.   if (err) {
  69.     console.error(`Renderer release failed, code is ${err.code}, message is ${err.message}`);
  70.   } else {
  71.     console.info('Renderer released.');
  72.   }
  73. });
复制代码


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 IT评测·应用市场-qidao123.com (https://dis.qidao123.com/) Powered by Discuz! X3.4