鸿蒙面试 2025-01-10

写了鉴权工具,你在项目中申请了那些权限?(常用权限)

  1. 位置权限 :

    ohos.permission.LOCATION_IN_BACKGROUND:允许应用在后台访问位置信息。
    ohos.permission.LOCATION:允许应用访问精确的位置信息。
    ohos.permission.APPROXIMATELY_LOCATION:允许应用访问大致的位置信息。
  2. 相机权限 :

    ohos.permission.CAMERA:允许应用访问相机设备。
  3. 麦克风权限 :

    ohos.permission.MICROPHONE:允许应用访问麦克风设备。
  4. 通讯录权限 :

    ohos.permission.READ_CONTACTS:允许应用读取通讯录。
    ohos.permission.WRITE_CONTACTS:允许应用写入通讯录。
  5. 日历权限 :

    ohos.permission.READ_CALENDAR:允许应用读取日历数据。
    ohos.permission.WRITE_CALENDAR:允许应用写入日历数据。
  6. 运动数据权限 :

    ohos.permission.ACTIVITY_MOTION:允许应用访问运动数据。此权限不支持在2in1设备上申请。
  7. 身体传感器权限 :

    ohos.permission.READ_HEALTH_DATA:允许应用读取健康数据。此权限仅穿戴设备可申请。
  8. 图片和视频权限 :

    ohos.permission.WRITE_IMAGEVIDEO:允许应用写入图片和视频。
    ohos.permission.READ_IMAGEVIDEO:允许应用读取图片和视频。
  9. 音乐和音频权限 :

    ohos.permission.WRITE_AUDIO:允许应用写入音频文件。
    ohos.permission.READ_AUDIO:允许应用读取音频文件。
  10. 跨应用关联权限 :

    ohos.permission.APP_TRACKING_CONSENT:允许应用进行跨应用跟踪。
  11. 多设备协同权限 :

    ohos.permission.DISTRIBUTED_DATASYNC:允许应用在多设备之间同步数据。
  12. 蓝牙权限 :

    ohos.permission.ACCESS_BLUETOOTH:允许应用访问蓝牙设备。
  13. 剪切板权限 :

    ohos.permission.READ_PASTEBOARD:允许应用读取剪切板数据。
  14. 文件夹权限 :

    ohos.permission.READ_WRITE_DOWNLOAD_DIRECTORY:允许应用读写下载目录。
    ohos.permission.READ_WRITE_DOCUMENTS_DIRECTORY:允许应用读写文档目录。此权限仅2in1设备可申请。

 

使用安全控件的话可以免申请权限?为啥不考虑使用安全控件?

使用安全控件确实可以在某些情况下免除你在鸿蒙系统中申请权限的需要。安全控件是一种系统提供的ArkUI组件,它们允许应用在用户点击后自动授权,无需额外的弹窗授权。这种方式不仅简化了开发者和用户的操作,还能够基于场景化授权,匹配用户的真实意图,从而减少弹窗打扰,提升用户体验。

安全控件的主要优点包括:

  1. 用户掌握授权时机 :用户可以在需要时才进行授权,授权范围也最小化。
  2. 简化操作 :开发者不必向应用市场申请权限1。
  3. 隐私合规 :安全控件坚持仅采集实现业务功能所必须的个人数据1。

目前,系统提供了三类安全控件:

  • 粘贴控件(PasteButton) :对应剪贴板读取特权,适用于需要读取剪贴板的场景1。
  • 保存控件(SaveButton) :对应媒体库写入特权,适用于需要保存文件到媒体库的场景1。
  • 位置控件(LocationButton) :对应精准定位特权,适用于需要在前台短暂使用位置信息的场景。

例如,在聊天界面发送实时定位信息的场景中,你可以直接使用位置控件来获得临时的精准定位授权,这样就可以避免长时间使用位置信息或后台使用位置信息的情况,从而满足权限最小化和提升隐私体验的要求2。

鉴于这些优势,使用安全控件成为了一种优选的解决方案,尤其是在应用不需要持续或后台访问敏感信息的情况下。这样不仅可以提高应用的隐私保护水平,还可以增强用户的信任和使用体验。

约束与限制

安全控件因其自动授权的特性,为了保障用户的隐私不被恶意应用获取,针对安全控件作了很多的限制。应用开发者需保证安全控件在应用界面上清晰可见、用户能明确识别,防止因覆盖、混淆等因素导致授权失败。

当因控件样式不合法导致授权失败的情况发生时,请开发者检查设备错误日志,过滤关键字"SecurityComponentCheckFail"可以获取具体原因。

可能会导致授权失败的问题(包括但不限于):

  • 字体、图标尺寸过小。

  • 安全控件整体尺寸过大。

  • 字体、图标、背景按钮的颜色透明度过高。

  • 字体或图标与背景按钮颜色过于相似。

  • 安全控件超出屏幕、超出窗口等,导致显示不全。

  • 安全控件被其他组件或窗口遮挡。

  • 安全控件的父组件有类似变形模糊等可能导致安全控件显示不完整的属性。


 

扫描二维码需要相机权限吗?拍照需要相机权限吗?

需要

在鸿蒙(HarmonyOS)开发中,使用相机进行扫码和拍照确实需要申请相机权限。这是因为相机操作涉及到用户的隐私和安全,因此应用在使用相机前必须获得用户的明确授权。

具体来说,对于相机权限的申请,您需要在应用的module.json5文件中配置相机权限,如下所示:

"permissions": [ "ohos.permission.CAMERA" ]

这行配置表示您的应用请求使用相机的权限。在应用运行时,您还需要通过代码请求用户授权,可以使用以下代码片段:

import { requestPermissionsFromUser } from '@ohos.ability';const permissions = ['ohos.permission.CAMERA'];
const result = await requestPermissionsFromUser(permissions);
if (result['ohos.permission.CAMERA'] === 'authorized') {console.log('Camera permission authorized');
} else {console.log('Camera permission denied');
}

这段代码会弹出一个授权对话框,让用户决定是否授予应用相机权限。只有当用户同意后,应用才能使用相机进行扫码或拍照。

因此,无论是进行二维码扫描还是拍照,您的应用都需要先确保已经获得了相机权限。这是保障用户隐私和应用功能正常运行的重要步骤。

不需要

系统通过提供系统Picker和安全控件两种方式,使得应用能够便捷地访问系统资源。这两种方法均依赖于系统的独立进程来实现,当应用拉起系统Picker或展示安全控件时,必须依赖用户的主动操作来获取资源或结果。这一流程避免了应用额外申请权限,同时,由于用户的积极参与,进一步增强了用户隐私和安全的保护。

系统Picker

系统Picker是拉起系统资源的一种方式,由于系统Picker已经获取了对应权限的预授权,开发者使用系统Picker时,无需再次申请权限也可临时受限访问对应的资源。

使用系统Picker组件拉起系统应用的场景主要有:联系人Picker(Contacts Picker),地图Picker,相机Picker(Camera Picker),扫码Picker,卡证识别Picker,文档扫描Picker,文件Picker,音频Picker和照片Picker(PhotoViewPicker)等,详细可参考拉起系统应用。

安全控件

安全控件是系统提供的一组系统实现的ArkUI组件,应用集成这类组件就可以实现在用户点击后自动授权,而无需弹窗授权。它们可以作为一种“特殊的按钮”融入应用页面,实现用户点击即许可的设计思路。

目前系统提供三类安全控件:粘贴控件(PasteButton)、保存控件(SaveButton)、位置控件(LocationButton)。

使用场景示例

以下列举了三个优先使用系统Picker或者安全控件的场景:

  1. 读写媒体库图片或视频:
    • 推荐方案(无需申请权限):使用PhotoViewPicker读取媒体库的图片与视频;使用安全控件中的保存控件保存媒体库的图片与视频。
    • 申请权限方案:申请受限权限ohos.permission.READ_IMAGEVIDEO或ohos.permission.WRITE_IMAGEVIDEO读取媒体库的图片与视频。
  2. 拉取系统相机拍照录制:
    • 推荐方案(无需申请权限):仅是需要拉起系统相机拍摄一张照片、录制一段视频,可直接使用CameraPicker,无需申请相机权限。
    • 申请权限方案:开发一个相机应用(或是在应用内开发相机模块)时,需按相机开发指导在开发前做好申请权限的准备。
  3. 访问当前位置:
    • 推荐方案(无需申请权限):应用仅需要在部分前台场景短暂地访问位置信息(例如定位城市、打卡、分享位置等),不需要长时间使用。此时,可以直接使用安全控件中的位置控件,免去权限申请和权限请求等环节,获得临时授权,满足权限最小化,提升用户的隐私体验。
    • 申请权限方案:如果需要长时间使用或是在后台使用位置信息,建议申请位置权限。

华为一键登入认证需要怎么做?

华为一键登录认证主要涉及以下几个步骤:

  1. 集成登录组件 :

    • 在您的应用中集成华为账号登录组件。这可以通过添加LoginWithHuaweiIDButton按钮来实现,该按钮支持一键登录功能。
  2. 配置权限 :

    • 在应用后台配置中,您需要申请quickLoginMobilePhone(华为账号一键登录)的scope权限。这是实现一键登录的前提条件。
  3. 用户交互设计 :

    • 按照华为的设计规范,设计一键登录的用户体验(UX)。这包括按钮的样式设计和页面布局,确保符合华为账号一键登录的视觉和体验标准。
  4. 处理登录逻辑 :

    • 当用户点击一键登录按钮后,应用会检查华为账号的登录状态。如果已经登录,应用将解析出用户的UnionIDOpenID和手机号码。
    • 如果用户在90天内没有验证记录,系统将触发短信验证流程,以确保手机号的有效性。
  5. 协议处理 :

    • 用户在使用一键登录前,必须同意《华为账号用户认证协议》1。您可以引导用户查看协议内容,并在用户同意后继续登录流程。
  6. 服务器配置 :

    • 应用服务器在获取华为账号绑定的手机号码时,必须确保服务器部署在中国大陆境内,因为该项服务当前仅限中国大陆用户使用。

通过以上步骤,您的应用就可以实现华为账号的一键登录功能,提供给用户快速、便捷的登录体验。


华为一键登入前端能获取到手机号码吗?

在华为账号一键登录功能中,前端确实能够获取到用户的手机号码。这一功能是通过华为的Account Kit实现的,它允许开发者在用户点击一键登录按钮后,获取用户绑定到华为账号的手机号码。

具体的实现方式如下:

  1. 用户点击一键登录按钮后,系统会检查用户在最近90天内是否有短信验证通过的记录。如果有,則直接返回手机号码;如果没有,系统将触发默认的短信验证流程。
  2. 这一过程中,开发者可以通过设置相应的回调函数来处理验证结果,例如在用户同意协议并完成登录后,可以使用continueLogin(callback)方法来处理登录结果。

 注意这里虽然获取到了手机号码,但是是匿名手机号码 例如 183******58


 

flutter怎么适配安卓和IOS?

Flutter 能够高效适配安卓(Android)与 iOS 平台,主要得益于以下几个关键要素:

  • 跨平台框架设计
    • 统一的编程语言:Flutter 使用 Dart 语言进行开发,它无需针对不同平台学习 Objective-C、Swift(iOS) 或 Java、Kotlin(Android)。开发者用一套代码,就能在两大主流移动平台构建应用,节省大量人力与学习成本。例如开发一款简单的待办事项应用,从创建任务列表、添加删除任务的逻辑,到界面布局与交互,代码只需编写一次。
    • 自绘引擎:Flutter 自带了一套高性能的自绘引擎,不依赖于原生系统控件。无论是在安卓的 Material Design 风格,还是 iOS 的扁平简约风格下,它能直接在画布上绘制出符合对应平台设计规范的 UI 元素,摆脱原生控件适配难题,像绘制一个自定义的渐变按钮,Flutter 可以精准呈现,不受原生系统限制。
  • 平台适配插件
    • 官方插件:Flutter 官方提供海量的插件库,覆盖常见的功能,如摄像头调用、地理位置获取、蓝牙连接等。针对安卓与 iOS 平台的特性差异,这些插件内部已做了适配处理。以地图插件为例,它能无缝对接谷歌地图(Android)和苹果地图(iOS),开发者使用时只需按统一接口操作,不必操心底层适配。
    • 社区插件:活跃的 Flutter 社区持续贡献丰富插件,补充官方遗漏的小众或新需求场景。当新的 iOS 系统特性发布,社区开发者会迅速反应,更新插件适配新功能,其他开发者拿来就能用,加快项目适配新平台特性的速度。
  • 遵循设计规范
    • 安卓 Material Design:对于安卓平台,Flutter 提供了遵循 Material Design 规范的组件库,开发者可以轻松组合出具有安卓风格的页面,像带水波纹特效的按钮、多层卡片式布局,让应用融入安卓生态。
    • iOS Human Interface Guidelines:对应 iOS,Flutter 同样能塑造贴合 iOS 设计理念的界面,如简洁大气的导航栏样式、细腻的动画过渡,确保应用在 iOS 设备上的用户体验符合苹果官方标准。
  • 编译打包流程
    • 差异化配置:Flutter 项目的构建脚本支持为安卓与 iOS 分别设置特定参数,比如安卓的不同应用市场渠道包配置、iOS 的 App Store 上架证书配置等。开发者可以在编译时精细调整,确保生成的应用包符合对应平台的上架、分发要求。
    • 多平台测试:Flutter CLI 工具方便开发者在安卓模拟器、真机以及 iOS 模拟器、真机上快速测试,通过多轮反复测试,排查因平台差异隐藏的兼容性问题,从布局错乱到功能异常,尽早发现并修复。

 

安卓的四大组件?

 

安卓的四大组件分别是 Activity(活动)、Service(服务)、Broadcast Receiver(广播接收器)以及 Content Provider(内容提供者),它们各自发挥着关键作用,协同构建起功能丰富的安卓应用:

  • Activity(活动)
    • 用户交互核心:作为安卓应用中直接与用户交互的可视化界面单元,每一个 Activity 通常对应一屏显示内容,像登录界面、主菜单、商品详情页等。它接收并响应用户的各类操作,例如触摸屏幕、按键点击,借此驱动页面跳转、数据更新、输入处理等交互流程。用户打开购物 APP,首先映入眼帘的首页 Activity,浏览商品时点击图片进入对应的商品详情 Activity,这一系列交互都发生在 Activity 层面。
    • 生命周期管理:有着严谨的生命周期,包括创建(onCreate)、启动(onStart)、恢复(onResume) 、暂停(onPause)、停止(onStop)、销毁(onDestroy)等阶段。开发者依据这些阶段精准把控资源分配与回收,比如在 onCreate 阶段初始化界面布局与数据,onDestroy 阶段释放不再使用的资源,防止内存泄漏。
  • Service(服务)
    • 后台持续运行:专注于在后台长时间执行特定任务,无需可视化界面。典型场景如音乐持续播放、文件后台下载、实时数据同步等。即使用户切换到其他 APP,对应的服务依然可以稳定运行,维持业务的连贯性,用户开启音乐播放服务后,即便切出去浏览新闻资讯,音乐也不停歇。
    • 跨组件协作:它能够与其他组件配合,通过 Intent 启动,也可以与 Activity、Broadcast Receiver 互动。例如,Activity 可以启动一个 Service 来执行耗时任务,之后通过广播接收器接收 Service 完成任务的反馈,实现不同组件间的接力协作。
  • Broadcast Receiver(广播接收器)
    • 消息监听响应:负责监听系统或应用发出的广播消息,安卓系统在众多关键事件节点,如开机、网络连接变化、电量不足等,都会发送广播;应用自身也能按需自定义广播。广播接收器捕捉到广播后,即刻执行预设的响应动作,手机电量低时,系统广播发出,电量预警类 APP 中的广播接收器收到信号,便及时提醒用户充电。
    • 系统集成与拓展:借助广播接收器,应用得以深度融入安卓系统生态,拓展功能边界。例如,安装新应用时系统广播触发,某些文件管理类 APP 借此广播可自动扫描新安装应用相关文件,实现智能管理。
  • Content Provider(内容提供者)
    • 数据共享桥梁:充当不同安卓应用间数据共享的媒介,把自身应用的数据以安全、可控的方式提供给其他授权应用访问。常见的,通讯录应用通过 Content Provider 将联系人数据开放,第三方短信、社交 APP 获取授权后,就能读取联系人,实现诸如短信群发、好友推荐等功能。
    • 数据封装与访问控制:它将数据封装成统一格式,配套设置访问权限规则,既保障数据拥有者的权益,也让有需求的应用合规获取数据,促进安卓应用间的数据流通与协同。 。


有了解Handler吗?Handler是什么?

在安卓开发中,Handler是一个极为关键的类,用于实现线程间通信,尤其是在处理主线程(UI 线程)与子线程交互时必不可少,主要体现在以下几方面:

  • 基本原理
    • Handler 关联着 MessageQueue(消息队列)与 Looper(循环器)。MessageQueue 是一个存放 Message(消息)的队列,按先进先出原则排列,用于暂存那些等待被处理的消息;Looper 则持续不断地从这个队列里取出消息,并把消息分发给对应的 Handler 去处理。每个线程默认只有一个 Looper,主线程的Looper在安卓应用启动时就自动创建好了,而子线程若要使用Handler,往往得手动创建Looper 。
  • 作用
    • 助力 UI 更新:安卓规定,耗时操作不能在主线程执行,否则会阻塞 UI,造成界面卡顿甚至 ANR(Application Not Responding,应用无响应)。当子线程完成耗时任务,如网络下载、数据库查询后,可将结果封装进 Message,借助 Handler 发送到主线程的 MessageQueue。主线程的Looper会从队列中取出该消息,再由对应的Handler处理,从而安全地更新 UI 。例如,子线程下载好一张图片后,把图片数据通过Handler传递给主线程,主线程更新 ImageView 来展示图片。
    • 线程间协调:不仅是子线程向主线程汇报,Handler也用于多线程间的信息传递与任务调度。不同子线程之间可以通过共享的 Handler 发送和接收消息,让它们的工作协同起来,有条不紊地完成复杂项目,像是在一个多线程处理多媒体文件的项目里,音频处理线程与视频处理线程靠Handler沟通进度、同步状态。
  • 使用方式
    • 创建与发送消息:首先得创建 Handler 对象,通常是在主线程创建,并重写 handleMessage 方法,用于定义收到消息后的处理逻辑。接着,在子线程生成 Message ,通过 Handler 的sendMessage 或 post方法把消息发送出去 。例如:
      Handler handler = new Handler() {@Overridepublic void handleMessage(Message msg) {// 处理消息,msg里携带了数据super.handleMessage(msg);}
      };new Thread(new Runnable() {@Overridepublic void run() {Message message = Message.obtain();// 设置消息内容handler.sendMessage(message);}
      }).start();

      在上述代码中,先定义Handler,子线程获取Message后发送给主线程的Handler处理。


 

HandlerMessageLooperMessageQueue 之间的关系?

Handler、Message、Looper 与 MessageQueue 在安卓开发的线程间通信机制里紧密协作,各自承担独特功能,共同构成一个高效的信息流转体系:

  • Message
    • 数据载体:它是整个通信流程的 “包裹”,用来承载各式各样的数据。无论是简单的整数、字符串,还是复杂的自定义对象,都能封装进Message。例如,子线程完成网络数据下载任务后,把下载的数据封装到Message里,以便传递给其他线程处理。Message自身带有一些属性字段,像是what,开发者可以为其赋值,以此区分不同类型的消息,方便接收方针对性处理。
  • MessageQueue
    • 消息队列:充当 “信息仓库”,是一个按先进先出(FIFO)原则组织的队列。所有待处理的Message都会被依次排入这个队列,无论消息来自哪个线程。这就好比银行营业厅的排队叫号系统,众多客户(消息)按先来后到顺序等待被服务(处理)。它负责暂存众多Message,保证消息处理的有序性。
  • Looper
    • 消息循环器:关联着MessageQueue,是驱动整个消息处理流程的 “引擎”。Looper会不断地从MessageQueue里取出Message,然后将其分发给对应的Handler去处理。每个线程默认情况下只会有一个Looper,主线程的Looper在安卓应用启动时便自动创建完成;而子线程如果要启用Handler,多数时候得手动搭建Looper体系,否则无法正常收发消息。Looper持续运转,不停地从队列中捞出消息,维持信息处理的动态循环。
  • Handler
    • 消息处理器:一方面,Handler是消息的 “投递员”,负责把Message发送到对应的MessageQueue。比如,子线程中有重要数据要传递给主线程更新 UI,就通过子线程创建的Handler把封装好数据的Message排入主线程的MessageQueue。另一方面,Handler也是消息的 “接收站”,它定义了handleMessage方法,当Looper把从MessageQueue中取出的Message转交给Handler时,就会触发该方法,进而处理消息内容,完成从消息发送、排队、提取到最终处理的完整闭环。

总结来说,Message承载具体数据进入MessageQueue排队等待,Looper驱动循环从队列中提取Message,再由Handler完成收发与处理,它们协同运作,保障安卓应用多线程间有条不紊地通信。


鸿蒙状态管理的装饰器?

  • @State
    • 功能:在使用鸿蒙的声明式开发范式时,@State 是极为重要的标识。当一个变量被标注为 @State,意味着这个变量用于保存组件的本地状态,它的任何改变都会触发组件的重新渲染。例如在一个简单的计数器组件里,把记录当前计数值的变量标记成 @State,每次点击增加或减少按钮改变这个值时,组件会迅速响应,更新界面显示的数字,精准呈现最新状态。
    • 原理:鸿蒙的 ArkUI 框架依赖这种机制追踪状态变化。被 @State 修饰的变量发生变更,框架能够感知,随即启动重新构建受影响的 UI 部分流程,避免了不必要的全页面刷新,优化性能的同时,也让 UI 与数据状态紧密同步。
  • @Prop
    • 功能:用于父子组件之间的数据传递与状态关联。如果父组件有某个数据需要传递给子组件,将该数据通过 @Prop 修饰后传递下去,子组件接收后就能基于这份数据展示内容或者执行逻辑。并且,子组件对这个数据的修改,也能反向通知父组件,维持父子组件间状态的协同更新。打个比方,父组件是一个商品列表,把选中商品的索引用 @Prop 传给子组件(商品详情展示框 ),子组件里切换商品详情时,父组件也能同步知晓,更新列表选中状态。
    • 优势:通过 @Prop 构建起清晰高效的父子组件交互通道,简化跨组件状态同步的复杂程度,提升代码可读性与可维护性,降低因状态不同步引发的 bug 出现概率。
  • @Link
    • 功能:建立父子组件间的双向数据绑定通道。无论是父组件数据变动影响子组件显示,还是子组件对数据的修改,都能实时反馈给父组件,让二者的数据状态时刻保持同步,双向互通。
    • 协同:和普通单向传递数据的机制相互补充,在父子组件交互场景下,要是数据需频繁来回变动,@Link 简化操作,无需手动编写过多更新逻辑,两边数据自动协同,提升开发效率与交互响应速度。
  • @Provide 与 @Consume
    • 功能:@Provide 负责将某个状态变量公开,使其成为全局或局部范围内可共享的 “资源池”;@Consume 则像一个 “取水口”,组件添加该装饰器就能获取、使用被提供的状态,让状态能跨多层级、多组件流通。
    • 协同:二者配合打破组件层级束缚,不同深度嵌套的组件依靠它们能基于共享状态协同运作,一处状态变更,各处相关消费该状态的组件自动更新,维持应用整体状态一致性。
  • @ObjectLink
    • 功能:聚焦于对象属性层面的变化追踪与同步。只要被观察对象的属性值出现变动,与之绑定、添加此装饰器的 UI 组件立刻知晓,随即更新展示内容,精准呈现对象最新状态。
    • 协同:搭配常规的对象操作逻辑,当业务频繁更新对象属性时,它保障 UI 与对象状态无缝衔接,无需额外干预,就能让相关 UI 与对象状态协同变化,优化用户界面实时响应效果。
  • @Observerd
    • 功能:自动监测被修饰变量或对象的属性改变,一旦发生变化,迅速触发相关 UI 的更新流程,让 UI 始终贴合数据最新情况,实现数据驱动 UI 更新。
    • 协同:融入整体数据处理与 UI 构建流程,和其他改变数据的操作协同,例如用户输入、后台数据推送,确保数据更新瞬间,UI 也能及时跟进,维持数据与展示的连贯性。
  • @StorageLink

    • 功能:它主要用于将组件内的状态与持久化存储相关联。当被标记的变量发生变化时,不仅会更新 UI,还会同步更新对应的存储数据,保障数据的持久保存。例如在一个笔记应用里,用户编辑笔记内容,被 @StorageLink 修饰的笔记文本变量,每一次改动,都会实时存入本地存储,无惧意外关闭应用导致数据丢失。
    • 协同:与本地存储模块紧密协作,像是和鸿蒙系统的文件系统 API 配合,一方面接收存储数据初始化组件状态,另一方面,持续推送状态更新,让存储系统与应用内状态互为表里,协同维护数据的完整性与即时性。
  • @StorageProp

    • 功能:和 @Prop 有相似之处,不过它额外承担了存储功能。父组件传递给子组件的数据通过 @StorageProp 修饰后,子组件对该数据的修改,除了反馈给父组件更新状态,还会自动存储下来。这在配置类信息传递场景很实用,比如一个主题切换设置,从父组件传到子组件,子组件调整后存好,下次启动应用依然生效。
    • 协同:整合父子组件交互流程与存储流程,让跨组件的数据流通环节和持久化环节无缝对接,降低开发者额外编写存储逻辑的负担,促使组件交互与数据留存高效协同。
  •  @Watcher
  • 功能
    • 当一个变量或者对象属性被标注为 @Watcher,它就进入了被 “监控” 状态。只要该变量或属性的值有所变动,与之绑定的 UI 组件会立刻感知到这些变化,从而触发对应的 UI 更新流程。这一机制让开发者能够轻松构建响应式的用户界面,把数据的动态更新与 UI 的实时刷新紧密关联起来。例如,在一个实时显示股票价格的鸿蒙应用中,代表股价的变量添加上 @Watcher,股价数据从后台推送过来发生改变时,对应的股价展示 UI 组件,像是文本标签、走势图,会马上更新显示最新价格。
  • 协同
    • 和数据获取逻辑协同:常与网络请求、本地数据读取等数据获取手段配合。后端源源不断推送新数据,或是本地数据库数据更新,被 @Watcher 标记的数据接收新值,随即驱动 UI 协同更新,保障展示内容与最新数据同步。
    • 与组件生命周期协同:在组件的生命周期各个阶段,@Watcher 持续发挥作用。从组件创建之初初始化数据,到后续运行中数据的多次更迭,无论组件处于活跃、暂停状态,只要数据改变,就能精准更新 UI,维持组件状态与 UI 展示在全生命周期内的一致性。
    • 跟其他状态管理机制协同:与 @State@Prop 等装饰器共存时,进一步细化状态管控。@State 侧重于本地组件状态,@Prop 管理父子组件间数据传递,@Watcher 则专注于数据变化触发 UI 更新这一关键环节,它们相互交织,为复杂应用的精准状态管理筑牢根基。

 

@Observed装饰器和@ObjectLink装饰器使用场景?

@Observed 和 @ObjectLink 是 HarmonyOS 开发中用于处理嵌套对象或数组的数据同步装饰器。它们主要用于确保数据模型中的属性变化能够反映到视图上,特别是在 dealing with nested objects or arrays。

@Observed 装饰器 @Observed 用于修饰类,它允许观察类的属性变化。这使得开发者可以在类的属性被修改时得到通知,从而执行相应的操作,如更新UI。以下是使用 @Observed 的一个示例:

@Observed
class Person {name: string;age: number;constructor(name: string, age: number) {this.name = name;this.age = age;}
}

在这个例子中,Person 类的 name 和 age 属性将被观察。当这些属性发生变化时,由于 Person 类被 @Observed 装饰,所以这些变化会被自动同步到使用 Person 实例的组件中。

@ObjectLink 装饰器 @ObjectLink 用于在父组件和子组件之间建立双向数据绑定。它通常与 @Observed 联合使用,以便将 @Observed 装饰的类的实例传递给子组件,并确保任何对类实例的修改都能反映到父组件和子组件的UI中。以下是使用 @ObjectLink 的一个示例:

@Component
struct MyPerson {@ObjectLink person: Personbuild() {Column() {Text(`姓名: $${this.person.name}`).fontSize(20).fontWeight(FontWeight.Bold)Text(`年龄: $${this.person.age}`).fontSize(15).fontWeight(FontWeight.Regular)}}
}

在这个例子中,MyPerson 组件通过 @ObjectLink 接收一个 Person 实例。这样,任何对 Person 实例属性的修改都会导致UI的更新。

通过这种方式,@Observed 和 @ObjectLink 帮助开发者管理和同步复杂的数据结构,简化代码


鸿蒙关系型数据库是哪个?使用场景是什么?

鸿蒙操作系统中的关系型数据库是指基于SQLite组件实现的数据库管理系统。这种数据库管理系统提供了一套完整的本地数据库管理机制,支持传统的增、删、改、查等操作,并且能够执行用户自定义的SQL语句,以应对更复杂的场景需求。

主要功能和参数:

  • RdbStore :这是操作关系型数据库的核心接口,通过这个接口可以执行各种数据库操作1。它需要三个参数:context(应用上下文)、config(数据库配置)和callback(回调函数)。
  • ResultSet :这是数据库查询结果的集合,允许用户遍历和访问查询结果。
  • RdbPredicates :用于定义数据库操作的条件1。

使用场景:

  1. 复杂关系数据存储 :适用于需要存储具有复杂关系的数据场景,如学校的学生成绩或公司的员工信息2。这些数据不仅包括基本的信息(如姓名、编号),还可能涉及多种多样的关联信息(如课程成绩、部门职位等)。
  2. 数据持久化 :关系型数据库提供了强大的数据持久化能力,能够确保数据的完整性和一致性,特别适合需要高频更新和复杂查询的应用。

注意事项:

  • 在使用过程中,建议单条数据不要超过2MB,以确保数据的正确读取。
  • 大数据量查询时,应尽量避免一次性查询过多数据,建议不超过5000条,并在TaskPool中执行此类操作,以减少对应用性能的影响。

 

数据库增删改查的API?

鸿蒙操作系统为SQLite数据库的增删改查操作提供了以下API:

  1. RdbStore接口 :

    • 获取RdbStore :getRdbStore(context: Context, config: StoreConfig, version: number, callback: AsyncCallback<RdbStore>): void12
      • 参数 :
        • context:应用的上下文。
        • config:与此RDB存储相关的数据库配置12。
        • version:数据库版本。
        • callback:指定callback回调函数,返回RdbStore对象12。
      • 说明 :通过这个接口,开发者可以获得一个RdbStore对象,进而执行数据库的操作。这个接口从API版本7开始支持,但已从API版本9起不再维护,推荐使用新的relationalStore模块1。
  2. relationalStore模块 :

    • 获取RdbStore :getRdbStore(context: Context, config: StoreConfig, callback: AsyncCallback<RdbStore>): void2
      • 参数 :
        • context:应用的上下文。
        • config:与此RDB存储相关的数据库配置。
        • callback:指定callback回调函数,返回RdbStore对象。
      • 说明 :这是推荐使用的 newer API,从API版本9开始支持。它允许开发者配置数据库操作的参数,并通过回调获取操作结果。

 relationalStore 的增删改查属性

insertSync

  • insertSync(table: string, values: ValuesBucket, conflict?: ConflictResolution):number
  • 向目标表中插入一行数据。由于共享内存大小限制为2Mb,因此单条数据的大小需小于2Mb,否则会查询失败。

batchInsertSync

  • batchInsertSync(table: string, values: Array<ValuesBucket>):number
  • 向目标表中插入一组数据。

updateSync

  • updateSync(values: ValuesBucket, predicates: RdbPredicates, conflict?: ConflictResolution):number
  • 根据RdbPredicates的指定实例对象更新数据库中的数据。由于共享内存大小限制为2Mb,因此单条数据的大小需小于2Mb,否则会查询失败。

deleteSync

  • deleteSync(predicates: RdbPredicates):number
  • 根据RdbPredicates的指定实例对象从数据库中删除数据。

querySync

  • querySync(predicates: RdbPredicates, columns?: Array<string>):ResultSet
  • 根据指定条件查询数据库中的数据。对query同步接口获得的resultSet进行操作时,若逻辑复杂且循环次数过多,可能造成freeze问题,建议将此步骤放到taskpool线程中执行。

 

鸿蒙数据库支持事务吗?事务是用来解决什么问题的?

鸿蒙的数据库支持事务。

事务主要用于解决数据库操作中的一系列复杂问题,确保数据的完整性、可靠性与一致性,具体如下:

  • 原子性问题
    • 场景:设想一个在线购票系统,当用户购买一张演出票时,数据库需要执行多个操作,比如减少对应场次的余票数量、将购票记录插入订单表、更新用户消费积分等。要是没有事务机制,在执行部分操作后系统突然崩溃,例如插入订单表成功了,但余票数量没更新,就会造成数据状态混乱。
    • 解决:事务具备原子性,将这一系列购票相关操作囊括其中,它们被当作一个不可拆分的单元。要么所有操作都顺利完成,要么只要其中一个环节出错,整个事务就会回滚,数据库状态恢复到事务开启前,避免出现 “半吊子” 数据。
  • 一致性问题
    • 场景:在银行转账业务里,从账户 A 转出一笔钱,必须等额转入账户 B,两边的账户余额总和要始终保持不变。若转账中途遭遇网络故障,只扣了 A 账户的钱,没能成功汇入 B 账户,就打破了账户余额的一致性。
    • 解决:事务把转账涉及的扣钱、转账操作绑定在一起,成功执行完所有步骤,才能提交事务,让数据库状态更新;要是过程中出现意外,事务回滚,维持账户数据的一致性。
  • 隔离性问题
    • 场景:多用户并发访问数据库的电商库存管理场景下,多个管理员同时处理商品入库、出库事宜。如果没有隔离机制,两个管理员同时读取某热门商品的库存数,又各自基于读取到的数据去更新库存,就容易导致库存数据错误,后续订单分配也会混乱。
    • 解决:事务设定不同的隔离级别,通过隔离并发事务,让每个事务执行时不受其他事务干扰。在高隔离级别下,当一个事务正在操作库存数据时,其他事务必须等待它完成,避免并发冲突,保证每个操作都基于准确的库存数据。
  • 持久性问题
    • 场景:对于关键业务数据录入,如医院病历系统,医生录入患者新的诊断信息,这些数据必须永久保存。要是录入后不久发生系统崩溃,数据丢失,后续治疗就失去依据。
    • 解决:事务一旦成功提交,其对数据库所做的修改就具有持久性,即使后续遭遇系统故障、重启,数据也不会丢失,因为数据库系统会运用日志、备份等机制保障已提交事务的数据安全落地。

navigation和router用过吗?哪个用的多一点?

Navigation和Router都是HarmonyOS中用于实现页面路由的机制,但它们在使用方式和提供的功能上有明显的差异。

Navigation作为一种新的路由解决方案,旨在提供更强大和灵活的功能。它允许开发者通过组件来构建页面,支持共享元素的转场,且没有路由数量限制。Navigation还支持嵌套在模态对话框中,提供更高的自定义性,如动效和属性设置。此外,Navigation在性能上也优于Router,因为它通过引用传递参数,支持动态加载组件。

Router则是一个较早的页面路由解决方案,虽然仍然使用广泛,但它的功能较为有限。Router支持通过URL地址进行页面跳转,但每个应用的页面栈容量限制为32个页面。Router也不支持一些高级功能,如共享元素动画和模态框中的路由嵌套。

根据这些信息,可以看出Navigation因为在功能性和性能上的优势,可能会被更多地用于新的HarmonyOS应用开发中。然而,Router由于其简洁性和与现有应用的兼容性,可能仍会在一些旧的应用或特定场景下使用。

总之,选择哪个工具取决于具体的应用需求和开发者的偏好。建议在新的项目中优先考虑使用Navigation,以利用其更多的功能和更好的性能。


navigation常用的生命周期?

其生命周期大致可分为三类,自定义组件生命周期、通用组件生命周期和自有生命周期。其中,aboutToAppear和aboutToDisappear是自定义组件的生命周期(NavDestination外层包含的自定义组件),OnAppear和OnDisappear是组件的通用生命周期。剩下的六个生命周期为NavDestination独有。

  • aboutToAppear:在创建自定义组件后,执行其build()函数之前执行(NavDestination创建之前),允许在该方法中改变状态变量,更改将在后续执行build()函数中生效。
  • onAppear:通用生命周期事件,NavDestination组件挂载到组件树时执行。
  • onWillAppear:NavDestination创建后,挂载到组件树之前执行,在该方法中更改状态变量会在当前帧显示生效。
  • onWillShow:NavDestination组件布局显示之前执行,此时页面不可见(应用切换到前台不会触发)。
  • onShown:NavDestination组件布局显示之后执行,此时页面已完成布局。
  • onWillHide:NavDestination组件触发隐藏之前执行(应用切换到后台不会触发)。
  • onHidden:NavDestination组件触发隐藏后执行(非栈顶页面push进栈,栈顶页面pop出栈或应用切换到后台)。
  • onWillDisappear:NavDestination组件即将销毁之前执行,如果有转场动画,会在动画前触发(栈顶页面pop出栈)。
  • onDisappear:通用生命周期事件,NavDestination组件从组件树上卸载销毁时执行。
  • aboutToDisappear:自定义组件析构销毁之前执行,不允许在该方法中改变状态变量。

 

想获取navigation那个页面的栈,需要在哪个生命周期获取(用于页面跳转的哪个对象)?

在HarmonyOS开发中,获取页面栈是通过NavPathStack对象实现的,这个对象是管理页面栈的核心。您可以通过以下方式获取页面栈的大小:

let size: number = this.pathStack.size();

这里的pathStack是一个NavPathStack的实例,它包含了所有页面的路径信息。您可以在需要进行页面跳转或在页面加载时获取这个信息,以便于管理页面的状态和跳转。

此外,您可以通过NavPathStack对象进行页面的push、pop和其他操作,这些操作都会影响到页面栈的状态。因此,建议在页面的aboutToAppearbuild方法中获取页面栈的信息,这两个方法分别在页面即将显示和页面构建时被调用,是获取页面栈的理想时机。


navigation怎么带参数跳转,跳转页怎接收参数?

在鸿蒙(HarmonyOS)开发中,通过Navigation组件传递参数通常涉及到两个方面:设置跳转参数和在目标页面中接收这些参数。以下是具体的实现步骤:

  1. 设置跳转参数 : 在跳转到另一个页面时,你可以通过NavPathStack来传递参数。例如,如果你从一个名为LoginPage的页面跳转到UserProfilePage,可以在pushPath方法中设置参数,如下所示:

    function pushPath(name, param, animated, onPop) {has.navPathStack.pushPath({name: name,param: param,animated: animated,onPop: onPop,callback: (err, res) => commonCallback('pushPath', err, res)});
    }
    

    在这个例子中,name是要跳转到的页面名称,param是要传递的参数。

  2. 在目标页面中接收参数 : 当你在目标页面中需要使用这些参数时,可以通过适当的方法来接收它们。这通常在目标页面的加载或初始化过程中完成,例如在UserProfilePage中,你可能会这样使用参数:

    function handleParams(params) {// 处理接收到的参数console.log("接收到的参数:", params);
    }
    

通过上述步骤,你可以在Navigation组件中有效地传递和接收参数,从而实现更复杂的功能和页面交互。

获取参数的方法

  1. 通过索引获取参数 :你可以使用 getParamByIndex(index) 方法来获取指定索引的 NavDestination 页面的参数信息。例如,如果你想要获取索引为1的页面参数,可以使用以下代码:

    let param = this.pathStack.getParamByIndex(1);
    
  2. 通过页面名获取参数 :如果你知道页面的名字,可以使用 getParamByName(name) 方法来获取所有名为 name 的 NavDestination 页面的参数信息1。例如,如果页面名为 PageOne,你可以这样获取它的参数:

    let params = this.pathStack.getParamByName("PageOne");

这些方法允许你在导航过程中灵活地获取和管理页面参数,从而实现复杂的功能组合和页面间的数据交互。

通过这些方法,你可以轻松地在页面之间传递和接收参数,这对于维护页面的状态和实现复杂的导航逻辑非常有用。


git场景题:假如我在一个分支上功能写了一半,现在我需要去另一个分支写其他功能,请问用哪个git命令可以解决这个问题

  1. 暂存当前工作进度
    • 执行 git stash ,该命令会把当前工作区(包括未提交的修改、暂存区新增内容等 )的所有改动收集起来,保存到一个类似栈的结构中,让工作目录立刻变得干净,仿佛从未做过这些修改一样。示例:
git stash
  1. 切换分支
    • 完成暂存后,就可以安心使用 git checkout 命令切换到目标分支,着手开发新功能。假设要切换到名为 new-branch 的分支,命令如下:
git checkout new-branch
  1. 恢复暂存的工作
    • 当在新分支的工作告一段落,想要回到之前未完成的功能分支接着开发时,先切回原来的分支:
git checkout original-branch
  • 接着,使用 git stash apply 把之前暂存的工作内容重新应用到当前工作区,让之前未完成的工作状态得以恢复,继续接着之前的进度开发:
git stash apply

需要注意的是,git stash apply 执行后,暂存的内容并不会从栈里删除。要是想删除这个已经应用的暂存项,可以额外执行 git stash drop;要是想一步到位,在应用的同时删除暂存内容,就用 git stash pop 命令。


http和https的区别,https为啥是安全的?

HTTP(超文本传输协议)和 HTTPS(超文本传输安全协议)主要有以下几方面区别:

  • 数据传输安全性
    • HTTP:使用明文传输数据,数据在网络传输过程中,是以原始的文本格式呈现,这就导致像用户名、密码、银行卡号这类敏感信息,非常容易被网络中的第三方截获,毫无保密性可言。
    • HTTPS:在传输层与应用层之间加入了 SSL/TLS 加密层,所有传输的数据都会先进行加密处理变成密文,接收方再用对应的密钥解密还原,就算数据中途被截取,第三方没有密钥也无法解读内容。
  • 端口使用
    • HTTP:默认工作在 80 端口,当我们在浏览器地址栏输入网址,不特别指定端口号时,浏览器就默认通过 80 端口去连接目标服务器,发起 HTTP 请求。
    • HTTPS:常用的工作端口是 443,同理,访问 HTTPS 网站,若不额外输入端口号,浏览器自动从 443 端口尝试建立连接。
  • 性能开销
    • HTTP:因为无需加密、解密操作,传输过程相对简洁快速,对服务器的计算资源占用较少,数据传输效率更高。
    • HTTPS:加密和解密过程会消耗大量的服务器 CPU、内存资源,尤其是在高并发场景下,额外的运算负担会让响应时间有所延长,性能开销明显更大。
  • 证书要求
    • HTTP:不强制要求使用数字证书,网站搭建部署更为简便直接,小型个人站点常采用 HTTP 协议。
    • HTTPS:必须申请权威 CA 机构颁发的 SSL/TLS 数字证书,以此证明服务器身份合法性,证书申请、更新等流程增加了网站运维成本与复杂度。

HTTPS 之所以安全,核心在于它的加密机制与身份认证体系:

  • 加密机制
    • 混合加密:结合了对称加密与非对称加密的优势。通信开始时,客户端与服务器利用非对称加密(公钥、私钥体系 )来安全交换对称加密所需的密钥 ,后续大量的数据传输就采用运算速度更快的对称加密。例如,客户端向服务器发起请求,服务器把公钥发给客户端,客户端利用公钥加密自己生成的对称密钥,再传回给服务器,之后双方就用这个对称密钥加密传输实际数据,兼顾了安全性与传输效率。
  • 身份认证
    • 数字证书:服务器部署 SSL/TLS 数字证书,证书里包含服务器的公钥以及服务器的身份信息,诸如域名、组织等。客户端访问服务器时,会验证证书真伪,只有通过 CA 机构严格审核验证的合法证书,客户端才会信任该服务器与之通信,杜绝中间人伪装成合法服务器窃取数据的隐患,防止遭遇钓鱼网站。

 

https是怎么加密的?

非对称加密与证书验证

  • 服务器发送证书:客户端向服务器发起 HTTPS 连接请求后,服务器会将包含自身公钥、域名、证书颁发机构、证书有效期等信息的数字证书发送给客户端。
  • 客户端验证证书:客户端接收到证书后,会验证证书的合法性,包括检查证书是否由可信的证书机构颁发、证书是否在有效期内、证书中的域名与服务器的实际域名是否一致等。如果证书验证不通过,客户端会中断连接;如果验证通过,则进入下一步。

对称加密密钥协商

  • 客户端生成对称密钥:客户端在本地生成一个随机数,用作对称加密的密钥。
  • 客户端加密并发送密钥:客户端取出证书中的公钥,用该公钥对随机数进行加密,将加密后的结果发送到服务端。
  • 服务端解密获取密钥:服务端收到客户端发来的加密后的密钥,先用自己的私钥解密,得到对称密钥。

数据加密传输

  • 使用对称密钥加密数据:客户端和服务器使用协商好的对称密钥对传输的数据进行加密和解密。在数据传输过程中,发送方将数据用对称密钥加密成密文后发送,接收方收到密文后用相同的对称密钥进行解密还原出原始数据。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/505450.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【硬件测试】基于FPGA的BPSK+帧同步系统开发与硬件片内测试,包含高斯信道,误码统计,可设置SNR

目录 1.硬件片内测试效果 2.算法涉及理论知识概要 2.1 bpsk 2.2 帧同步 3.Verilog核心程序 4.开发板使用说明和如何移植不同的开发板 5.完整算法代码文件获得 1.硬件片内测试效果 本文是之前写的文章 《基于FPGA的BPSK帧同步系统verilog开发,包含testbench,高斯信道,误…

MySQL 视图 存储过程与存储函数

第十四章_视图、第十五章 _存储过程与存储函数 1.常见的数据库对象 1. 表&#xff08;Table&#xff09; 用于存储结构化数据的基本对象&#xff0c;由行&#xff08;记录&#xff09;和列&#xff08;字段&#xff09;组成。 2. 视图&#xff08;View&#xff09; 基于一…

Chrome_60.0.3112.113_x64 单文件版 下载

单文件&#xff0c;免安装&#xff0c;直接用~ Google Chrome, 免費下載. Google Chrome 60.0.3112.113: Chrome 是 Google 開發的網路瀏覽器。它的特點是速度快,功能多。 下载地址: https://blog.s3.sh.cn/thread-150-1-1.htmlhttps://blog.s3.sh.cn/thread-150-1-1.html

CTFshow—文件包含

Web78-81 Web78 这题是最基础的文件包含&#xff0c;直接?fileflag.php是不行的&#xff0c;不知道为啥&#xff0c;直接用下面我们之前在命令执行讲过的payload即可。 ?filephp://filter/readconvert.base64-encode/resourceflag.php Web79 这题是过滤了php&#xff0c;…

python学opencv|读取图像(二十九)使用cv2.getRotationMatrix2D()函数旋转缩放图像

【1】引言 前序已经学习了如何平移图像&#xff0c;相关文章链接为&#xff1a; python学opencv|读取图像&#xff08;二十七&#xff09;使用cv2.warpAffine&#xff08;&#xff09;函数平移图像-CSDN博客 在此基础上&#xff0c;我们尝试旋转图像的同时缩放图像。 【2】…

24下半年软考「单独划线」合格标准已公布!

2024年下半年计算机技术与软件专业技术资格考试单独划线地区合格标准已公布&#xff01; 其中初级和中级单独划线地区合格标准各科目均为39分&#xff0c;高级各科目为40分&#xff0c;符合单独划线地区的同学可以去申请证书了。 一、证书效力 在单独划线地区报名参加相关职业…

Linux第一课:c语言 学习记录day06

四、数组 冒泡排序 两两比较&#xff0c;第 j 个和 j1 个比较 int a[5] {5, 4, 3, 2, 1}; 第一轮&#xff1a;i 0 n&#xff1a;n个数&#xff0c;比较 n-1-i 次 4 5 3 2 1 // 第一次比较 j 0 4 3 5 2 1 // 第二次比较 j 1 4 3 2 5 1 // 第三次比较 j 2 4 3 2 1 5 // …

前端用json-server来Mock后端返回的数据处理

<html><body><div class"login-container"><h2>登录</h2><div class"login-form"><div class"form-group"><input type"text" id"username" placeholder"请输入用户名&q…

是德科技M9010A PXIe 机箱+M9037A模块,台式应用的理想之选

Keysigh是德科技M9010A PXIe 机箱M9037A模块 M9010A PXIe 10 插槽 Gen 3 机箱提供***的灵活性、兼容性和性能&#xff0c;而且外形更小巧&#xff0c;是台式应用的理想之选。它拥有 8 个 PXIe 混合插槽&#xff0c;使系统设计人员能够更灵活地混合和搭配 PXIe 和混合兼容模块的…

【算法刷题】leetcode hot 100 滑动窗口

文章目录 3. 无重复字符的最长子串438. 找到字符串中所有字母异位词总结 3. 无重复字符的最长子串 leetcode&#xff1a;https://leetcode.cn/problems/longest-substring-without-repeating-characters/?envTypestudy-plan-v2&envIdtop-100-liked 滑动窗口 &#xff0…

企业级PHP异步RabbitMQ协程版客户端 2.0 正式发布

概述 workerman/rabbitmq 是一个异步RabbitMQ客户端&#xff0c;使用AMQP协议。 RabbitMQ是一个基于AMQP&#xff08;高级消息队列协议&#xff09;实现的开源消息组件&#xff0c;它主要用于在分布式系统中存储和转发消息。RabbitMQ由高性能、高可用以及高扩展性出名的Erlan…

基于SpringBoot的洗浴管理系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…

直流无刷电机控制(FOC):电流模式

目录 概述 1 系统框架结构 1.1 硬件模块介绍 1.2 硬件实物图 1.3 引脚接口定义 2 代码实现 2.1 软件架构 2.2 电流检测函数 3 电流环功能实现 3.1 代码实现 3.2 测试代码实现 4 测试 概述 本文主要介绍基于DengFOC的库函数&#xff0c;实现直流无刷电机控制&#x…

51单片机——串口通信(重点)

1、通信 通信的方式可以分为多种&#xff0c;按照数据传送方式可分为串行通信和并行通信&#xff1b; 按照通信的数据同步方式&#xff0c;可分为异步通信和同步通信&#xff1b; 按照数据的传输方向又可分为单工、半双工和全双工通信 1.1 通信速率 衡量通信性能的一个非常…

oracle位运算、左移右移、标签算法等

文章目录 位运算基础与或非同或同或应用场景 异或异或应用场景 什么是真值表 oracle基础函数创建bitor(按位或)函数bitnot(按位非)函数bitxor(按位异或)函数左移函数BITSHIFT()函数(实测不可用&#xff0c;废弃掉该方案)右移函数(略&#xff0c;有此场景吗?) 实际应用资质字典…

VS2015 + OpenCV + OnnxRuntime-Cpp + YOLOv8 部署

近期有个工作需求是进行 YOLOv8 模型的 C 部署&#xff0c;部署环境如下 系统&#xff1a;WindowsIDE&#xff1a;VS2015语言&#xff1a;COpenCV 4.5.0OnnxRuntime 1.15.1 0. 预训练模型保存为 .onnx 格式 假设已经有使用 ultralytics 库训练并保存为 .pt 格式的 YOLOv8 模型…

python无需验证码免登录12306抢票 --selenium(2)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 [TOC](python无需验证码免登录12306抢票 --selenium(2)) 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 就在刚刚我抢的票&#xff1a;2025年1月8日…

本地手集博客id“升级”在线抓取——简陋版——(2024年终总结1.1)

我之前每每发布笔记都用csv纯文本记录&#xff0c;一个机缘巧得文章列表api实现在线整理自已的文章阅读量数据。 (笔记模板由python脚本于2025年01月10日 18:48:25创建&#xff0c;本篇笔记适合喜欢钻牛角尖的coder翻阅) 【学习的细节是欢悦的历程】 Python官网&#xff1a;htt…

工业 4G 路由器赋能远程医疗,守护生命线

在医疗领域&#xff0c;尤其是偏远地区的医疗救治场景中&#xff0c;工业 4G 路由器正发挥着无可替代的关键作用&#xff0c;宛如一条坚韧的 “生命线”&#xff0c;为守护患者健康持续赋能。 偏远地区医疗资源相对匮乏&#xff0c;常常面临着专业医生短缺、诊疗设备有限等困境…

【python基础——异常BUG】

什么是异常(BUG) 检测到错误,py编译器无法继续执行,反而出现错误提示 如果遇到错误能继续执行,那么就捕获(try) 1.得到异常:try的执行,try内只可以捕获一个异常 2.预案执行:except后面的语句 3.传入异常:except … as uestcprint(uestc) 4.没有异常:else… 5.鉴定完毕,收尾的语…