HarmonyOS应用六之应用程序进阶一

目录:

    • 1、UIAbility的冷启动和UIAbility热启动
    • 2、静态资源和动态资源的访问
    • 3、页面跳转
      • 3.1、页面返回跳转
    • 4、HAR的ArkUI组件、接口、资源,供其他应用或当前应用的其他模块引用
      • 4.1、导出HAR的ArkUI组件
      • 4.2、引用HAR的ArkUI组件
    • 5、循环渲染
    • 6、状态管理最佳实践
    • 7、AppStorage的使用精细化拆分复杂状态

1、UIAbility的冷启动和UIAbility热启动

  • UIAbility冷启动:指的是UIAbility实例处于完全关闭状态下被启动,这需要完整地加载和初始化UIAbility实例的代码、资源等。

目标UIAbility冷启动时,在目标UIAbility的onCreate()生命周期回调中,接收调用方传过来的参数。然后在目标UIAbility的onWindowStageCreate()生命周期回调中,解析调用方传递过来的want参数,获取到需要加载的页面信息url,传入windowStage.loadContent()方法。

import { AbilityConstant, Want, UIAbility } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { window, UIContext } from '@kit.ArkUI';const DOMAIN_NUMBER: number = 0xFF00;
const TAG: string = '[EntryAbility]';export default class EntryAbility extends UIAbility {funcAbilityWant: Want | undefined = undefined;uiContext: UIContext | undefined = undefined;onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {// 接收调用方UIAbility传过来的参数this.funcAbilityWant = want;}onWindowStageCreate(windowStage: window.WindowStage): void {// Main window is created, set main page for this abilityhilog.info(DOMAIN_NUMBER, TAG, '%{public}s', 'Ability onWindowStageCreate');// Main window is created, set main page for this abilitylet url = 'pages/Index';if (this.funcAbilityWant?.parameters?.router && this.funcAbilityWant.parameters.router === 'funcA') {url = 'pages/Page_ColdStartUp';}windowStage.loadContent(url, (err, data) => {// ...});}
}
  • UIAbility热启动:指的是UIAbility实例已经启动并在前台运行过,由于某些原因切换到后台,再次启动该UIAbility实例,这种情况下可以快速恢复UIAbility实例的状态。

在应用开发中,会遇到目标UIAbility实例之前已经启动过的场景,这时再次启动目标UIAbility时,不会重新走初始化逻辑,只会直接触发onNewWant()生命周期方法。为了实现跳转到指定页面,需要在onNewWant()中解析参数进行处理。

例如短信应用和联系人应用配合使用的场景。

1、用户先打开短信应用,短信应用的UIAbility实例启动,显示短信应用的主页。
2、用户将设备回到桌面界面,短信应用进入后台运行状态。
3、用户打开联系人应用,找到联系人张三。
4、用户点击联系人张三的短信按钮,会重新启动短信应用的UIAbility实例。
5、由于短信应用的UIAbility实例已经启动过了,此时会触发该UIAbility的onNewWant()回调,而不会再走onCreate()和onWindowStageCreate()等初始化逻辑。

import { AbilityConstant, Want, UIAbility } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import type { Router, UIContext } from '@kit.ArkUI';
import type { BusinessError } from '@kit.BasicServicesKit';const DOMAIN_NUMBER: number = 0xFF00;
const TAG: string = '[EntryAbility]';export default class EntryAbility extends UIAbility {funcAbilityWant: Want | undefined = undefined;uiContext: UIContext | undefined = undefined;// ...onNewWant(want: Want, launchParam: AbilityConstant.LaunchParam): void {if (want?.parameters?.router && want.parameters.router === 'funcA') {let funcAUrl = 'pages/Page_HotStartUp';if (this.uiContext) {let router: Router = this.uiContext.getRouter();router.pushUrl({url: funcAUrl}).catch((err: BusinessError) => {hilog.error(DOMAIN_NUMBER, TAG, `Failed to push url. Code is ${err.code}, message is ${err.message}`);});}}}
}

热启动是前提得有冷启动,就是应用启动后处于后台运行,当从其他位置点击进来需要进入后台运行的应用程序时就需要使用到热启动。

2、静态资源和动态资源的访问

在组件中,经常需要使用字符串、图片等资源。HSP中的组件需要使用资源时,一般将其所用资源放在HSP包内,而非放在HSP的使用方处,以符合高内聚低耦合的原则。
在工程中,常通过 r / r/ r/rawfile的形式引用应用资源。可以用 r / r/ r/rawfile访问本模块resources目录下的资源,如访问resources目录下定义的图片src/main/resources/base/media/example.png时,可以用$r(“app.media.example”)

// library/src/main/ets/pages/Index.ets
// 正确用例
Image($r('app.media.example')).id('example').borderRadius('48px')
// 错误用例
Image("../../resources/base/media/example.png").id('example').borderRadius('48px')

将需要对外提供的资源封装为一个资源管理类:

// library/src/main/ets/ResManager.ets
export class ResManager{static getPic(): Resource{return $r('app.media.pic');}static getDesc(): Resource{return $r('app.string.shared_desc');}
}

对外暴露的接口,需要在入口文件index.ets中声明:

// library/index.ets
export { ResManager } from './src/main/ets/ResManager';

3、页面跳转

在这里插入图片描述
其中router.pushUrl方法的入参中url的内容为:

'@bundle:com.samples.hspsample/library/ets/pages/Menu'

url内容的模板为:

'@bundle:包名(bundleName)/模块名(moduleName)/路径/页面所在的文件名(不加.ets后缀)'

3.1、页面返回跳转

在这里插入图片描述

页面返回router.back方法的入参中url说明:

如果从HSP页面返回HAP页面,url的内容为:

'pages/Index'

url内容的模板为:

'页面所在的文件名(不加.ets后缀)'

如果从HSP1的页面跳到HSP2的页面后,需要返回到HSP1的页面,url的内容为:

'@bundle:com.samples.hspsample/library/ets/pages/Menu'

url内容的模板为:

'@bundle:包名(bundleName)/模块名(moduleName)/路径/页面所在的文件名(不加.ets后缀)'

4、HAR的ArkUI组件、接口、资源,供其他应用或当前应用的其他模块引用

4.1、导出HAR的ArkUI组件

Index.ets文件是HAR导出声明文件的入口,HAR需要导出的接口,统一在Index.ets文件中导出。Index.ets文件是DevEco Studio默认自动生成的,用户也可以自定义,在模块的oh-package.json5文件中的main字段配置入口声明文件,配置如下所示:

{"main": "Index.ets"
}

导出ArkUI组件
ArkUI组件的导出方式与ts的导出方式一致,通过export导出ArkUI组件,示例如下:

// library/src/main/ets/components/mainpage/MainPage.ets
@Component
export struct MainPage {@State message: string = 'HAR MainPage';build() {Column() {Row() {Text(this.message).fontSize(32).fontWeight(FontWeight.Bold)}.margin({ top: '32px' }).height(56).width('624px')Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center, alignContent: FlexAlign.Center }) {Column() {Image($r('app.media.pic_empty')).width('33%')Text($r('app.string.empty')).fontSize(14).fontColor($r('app.color.text_color'))}}.width('100%').height('90%')}.width('100%').height('100%').backgroundColor($r('app.color.page_background'))}
}

HAR对外暴露的接口,在Index.ets导出文件中声明如下所示:

// library/Index.ets
export { MainPage } from './src/main/ets/components/mainpage/MainPage';

4.2、引用HAR的ArkUI组件

HAR的依赖配置成功后,可以引用HAR的ArkUI组件。ArkUI组件的导入方式与ts的导入方式一致,通过import引入HAR导出的ArkUI组件,示例如下所示:

// entry/src/main/ets/pages/IndexSec.ets
import { MainPage } from 'library';@Entry
@Component
struct IndexSec {build() {Row() {// 引用HAR的ArkUI组件MainPage()}.height('100%')}
}

5、循环渲染

@Entry
@Component
struct Parent {@State simpleList: Array<string> = ['one', 'two', 'three'];build() {Row() {Column() {ForEach(this.simpleList, (item: string) => {ChildItem({ item: item })}, (item: string) => item)}.width('100%').height('100%')}.height('100%').backgroundColor(0xF1F3F5)}
}@Component
struct ChildItem {@Prop item: string;build() {Text(this.item).fontSize(50)}
}

运行效果如图所示:
在这里插入图片描述
此次是循环遍历数据,通过@Prop监听父组件中的值,进行字体大小为50的逻辑处理。

6、状态管理最佳实践

@Observed
class Translate {translateX: number = 20;
}@Entry
@Component
struct UnnecessaryState1 {@State translateObj: Translate = new Translate(); // 同时存在读写操作,并关联了Button组件,推荐使用状态变量buttonMsg = 'I am button'; // 仅读取变量buttonMsg的值,没有任何写的操作,直接使用一般变量即可build() {Column() {Button(this.buttonMsg).onClick(() => {animateTo({duration: 50}, () => {this.translateObj.translateX = (this.translateObj.translateX + 50) % 150; // 点击时给变量translateObj重新赋值})})}.translate({x: this.translateObj.translateX // 读取translateObj中的值})}
}

没有关联任何UI组件的状态变量和没有修改过的状态变量不应该定义为状态变量,直接使用一般变量即可,否则会影响性能。

在这里插入图片描述

7、AppStorage的使用精细化拆分复杂状态

对AppStorage的使用,以“HMOS世界App”中共享用户信息和用户收藏信息为例,描述如何拆分状态存储。用户信息和用户收藏信息涉及的模块和界面展示如下:
在这里插入图片描述

  • “我的”模块顶部有展示用户信息的组件“UserInfoView”,底部有展示用户收藏列表,列表卡片上需要高亮展示用户是否点赞了当前文章。
  • “探索”模块首页展示技术文章列表,列表卡片上同样需要展示用户是否点赞了当前文章。
  • 当两个模块中任一模块的卡片有点赞交互时,需要同步用户是否对文章点赞的状态给另一个模块。

当前项目中已经使用AppStorage存储用户信息UserData,UserData的数据结构和“UserInfoView”组件使用UserData状态展示用户信息的代码如下:

//用户信息UserData的数据结构
export interface UserData {id: string;username: string;description: string;// ...
}//在业务类中获取服务端用户信息
getUserData(): void {this.userAccountRepository.getUserData().then((data: UserData) => {//1.将用户信息数据存储到AppStorage中AppStorage.setOrCreate('userData', data);})
}//“我的”模块顶部展示用户信息的视图组件
@Component
struct UserInfoView {//2.在UI中使用@StorageLink装饰器接收AppStorage中存储的用户信息@StorageLink('userData') userData: UserData | null = null;build() {Column() {Row({ space: Constants.MIDDLE_SPACE }) {// ...Column() {//3.展示用户信息userData中的用户名Text(this.userData? this.userData.username : $r('app.string.default_login'))// ...}}// ...}// ...}
}

现在“探索“模块和“我的“模块需要共享用户的收藏列表信息,只需要共享收藏的文章id数组即可。不同模块间的状态共享考虑将其也存储在AppStorage中,有如下两种存储方案:

  1. 收藏信息也是用户信息的一部分,将收藏信息作为用户信息userData的一个属性,存储在当前AppStorage里key值为“userData”的变量上。

  2. 收藏信息单独存入AppStorage中,不与用户信息userData绑定。

第一种方案的代码实现如下:

export interface UserData {id: string;username: string;description: string;// 1. 在用户信息UserData上增加用户收藏的资源列表id信息类型定义collectedIds: string[];// ...
}//在业务类中获取服务端用户信息
getUserData(): void {this.userAccountRepository.getUserData().then((data: UserData) => {//2.将用户信息数据存储到AppStorage中AppStorage.setOrCreate('userData', data);})
}// 探索模块的文章卡片组件
@Component
export struct ArticleCardView {//3.在探索文章列表卡片上通过@StorageLink装饰器获取用户信息对象userData@StorageLink('userData') userData: UserData | null = null;@Prop articleItem: LearningResource = new LearningResource();//4.根据收藏信息数组计算当前文章是否被收藏isCollected(): boolean {return this.userData && this.userData.collectedIds.some((id: string) => id === this.articleItem.id);}//7.处理界面点赞交互逻辑:使用@StorageLink装饰器接收的userData状态子属性collectedIds被修改后,新值会同步到AppStorage中handleCollected(): void {const index = this.userData?.collectedIds.findIndex((id: string) => id === this.articleItem.id);if (index === -1) {this.userData?.collectedIds.push(resourceId);} else {this.userData?.collectedIds.splice(index, 1);}// ...}build(){ActionButtonView({//5.根据当前文章是否被用户收藏,判断收藏图标是否高亮imgResource: this.isCollected() ? $r('app.media.btn_favorites_on') : $r('app.media.btn_favorites_normal'),count: this.articleItem.collectionCount,textWidth: $r('app.float.star_icon_width')}).onClick(() => {//6.用户点击收藏图标时,调用处理收藏状态修改的函数this.handleCollected();})}
}

这种实现方案下,当用户在“UserInfoView ”组件上重新修改用户描述信息userData.description属性值时,属性值变化将同步回AppStorage中。ArkUI监听到AppStorage中key值为“userData”的值变化,随后通知所有使用了AppStorage中key值为“userData”的组件重新渲染。

在上述界面中,“我的“模块中展示用户信息的组件“UserInfoView ”会重新渲染。由于“探索”模块的文章卡片组件ArticleCardView 通过@StorageLink装饰器绑定了AppStorage中key值为“userData”的变量,所有的文章卡片组件也都会重新渲染。而这些组件与用户描述信息无关,不应该被描述信息的修改变化影响,从而导致渲染刷新。

改为使用上述第二种方案实现,代码如下:

//在业务类中获取用户信息
getUserData(): void {this.userAccountRepository.getUserData().then((data: UserData) => {//1.将用户收藏信息单独数据存储到AppStorage中AppStorage.setOrCreate('collectedIds', data.collectedIds);AppStorage.setOrCreate('userData', data);})
}// 探索模块的文章卡片组件
@Component
export struct ArticleCardView {//2.通过@StorageLink装饰器获取AppStorage中存储的收藏信息@StorageLink('collectedIds') collectedIds: string[] = [];@Prop articleItem: LearningResource = new LearningResource();//3.根据收藏信息数组计算当前文章是否被收藏  isCollected(): boolean {return this.collectedIds.some((id: string) => id === this.articleItem.id);}//6.处理界面点赞交互逻辑:使用@StorageLink装饰器接收的状态collectedIds被修改后,新值会同步到AppStorage中handleCollected(): void {const index = this.collectedIds.findIndex((id: string) => id === this.articleItem.id);if (index === -1) {this.collectedIds.push(resourceId);} else {this.collectedIds.splice(index, 1);}// ...}build(){ActionButtonView({//4.根据当前文章是否被用户收藏,判断收藏图标是否高亮imgResource: this.isCollected() ? $r('app.media.btn_favorites_on') : $r('app.media.btn_favorites_normal'),count: this.articleItem.collectionCount,textWidth: $r('app.float.star_icon_width')}).onClick(() => {//5.用户点击收藏图标时,调用处理收藏状态修改的函数this.handleCollected();})}
}

在此方案中,由于文章卡片组件没有绑定AppStorage中key值为“userData”的变量,当用户编辑修改了用户描述userData.description的值时, 文章卡片组件不会重新渲染。

并且,当用户点击文章卡片上的收藏按钮修改文章收藏状态时,变化同步回AppStorage中的key值为“collectedIds”的变量。ArkUI监听到AppStorage中key值为“collectedIds”的值变化,只会通知所有绑定了AppStorage中key值为“collectedIds”变量的组件重新渲染,不会造成“我的“模块用户信息组件“UserInfoView ”重新渲染。

因此,从性能的角度考虑,在使用LocalStorage或AppStorage装饰器存储状态变量时需要合理设计状态的数据结构,避免无意义的渲染刷新。

说明:
过分追求状态结构拆分可能在某些场景导致组件设计过度,不利于维护。此时,可以将对象或类上经常一起改变的几个属性聚合成一个新的对象或类模型,并使用@Observed装饰器修饰,再作为属性挂载到之前的对象或类上。通过此方法,当属性变化时ArkUI只会通知变化给新的对象或类,不会通知最上层的对象。这样既可以有效的减少无用渲染次数,又能使代码更好维护。

如类ClassA上存在属性b、c、d。其中c和d经常一起发生变化,即当c的状态修改时同时也要修改d的状态。

class ClassA{b: string;c: number;d: boolean;
}

此时,将c和d组合在一起做为新的类ClassE的属性并使用@Observed装饰器修饰。对于ClassA去掉c、d属性,新增属性e且其类型为ClassE,设计如下:

class ClassA{b: string;e: ClassE;
}
@Observed
class ClassE{c: number;d: boolean;
}

使用此方案,在AppStorage中存入数据结构为ClassA的变量。当ClassA实例的属性e中的属性c的值变化时,状态变化会通知使用ClassE实例的组件重新渲染,不会通知所有使用AppStorage中ClassA实例的组件更新,即只使用了ClassA实例b属性的组件不会重新渲染。

总结:
上述状态变量案例也可以使用此方法去实现防止资源的浪费,使用@Observed修饰一个新类里面包含collectedIds,当collectedIds发生改变只会刷新新类,而不会刷新UserData,从而避免了资源的浪费。

伪代码如下:

export interface UserData {id: string;username: string;description: string;e: ClassE;@Observed
class ClassE{// 1. 在用户信息UserData上增加用户收藏的资源列表id信息类型定义collectedIds: string[];// ...
}
}

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

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

相关文章

【MySQL】多表联合查询常见练习题

数据库表如下&#xff1a; teacher&#xff1a;老师表 course&#xff1a;课程表 student&#xff1a;学生表 class&#xff1a;班级表 sc&#xff1a;成绩表 一、根据上面5张表写sql语句 1. 查询” 01 “课程比” 02 “课程成绩高的学生的信息及课程分数 select student.…

在Ubuntu 20.04中安装CARLA

0. 引言 CARLA (Car Learning to Act) 是一款开源自动驾驶模拟器&#xff0c;其支持自动驾驶系统全管线的开发、训练和验证&#xff08;Development, Training, and Validation of autonomous driving systems&#xff09;。Carla提供了丰富的数字资产&#xff0c;例如城市布局…

国外电商系统开发-运维系统功能清单开发

一、最终效果图 二、功能清单 功能 描述 自定义日志绘图 根据Nginx、Apache登录日志文件绘图&#xff0c;绘图数据包括&#xff1a;访问量走势&#xff0c;500错误&#xff0c;200正确百分比等 创建服务器 加入服务器 主机状态自动检查 加入主机到系统后&#xff0c;系统…

MyBatis——ORM

MyBatis——ORM 验证映射配置ResultType本质是ResultMap具体的转换逻辑 概括的说&#xff0c;MyBatis中&#xff0c;对于映射关系的声明是由开发者在xml文件手动完成的。比如对查询方法而言&#xff0c;你需要显式声明ResultType或ResultMap&#xff0c;这里其实就是在定义数据…

(16)MATLAB仿真Nakagami-m分布1

文章目录 前言一、Nakagami分布二、MATLAB建模代码三、仿真结果画图四、总结 前言 Nakagami衰落模型最初是由于该模型与短波电离层传播的经验结果相匹配而提出的。它还用于仿真来自多个干扰源的情况&#xff0c;因为多个独立且同分布&#xff08;i.i.d&#xff09;的瑞利分布随…

基于四种网络结构的WISDM数据集仿真及对比:Resnet、LSTM、Shufflenet及CNN

在上节中&#xff0c;我们已经详细介绍了WISDM数据集及如何使用CNN网络训练&#xff0c;得到了六个维度的模型仿真指标及五个维度的可视化分析&#xff0c;那么现在我们将训练模型推广到其他网路结构中去&#xff0c;通过仿真实验来对比一下不同网络之间对于WISDM数据集的训练效…

大语言模型入门(三)——提示词编写注意事项

一、提示词编写原则 提示词的编写应当遵循两个原则&#xff0c; 一个是指令必须清晰且具体&#xff0c;另一个是应当给模型充足的时间去思考。首先&#xff0c;你的指令足够清晰和具体&#xff0c;才能让大模型明确你需要它执行的任务&#xff0c;从而降低我们得到无关或者不正…

kubernetes-强制删除命名空间

一、故障现象 1、删除命名空间卡住、强制删除也卡住 2、其他终端显示命名空间下无资源 二、处理步骤 1、kubectl get namespace cilium-test -o json > temp.json 获取你需要删除的命名空间json描述文件。 2、修改finalize字段 3、替换 kubectl replace --raw "/api/v1…

Pikachu-xss防范措施 - href输出 js输出

总体原则&#xff1a; 输入做过滤&#xff0c;输出做转义 过滤&#xff1a;根据业务需要进行过滤&#xff0c;如&#xff1a;输入点要求输入手机号&#xff0c;则只允许输入手机号格式的数字&#xff1b; 转义&#xff1a;所有输出到前端的数据&#xff0c;都根据输出点进行转…

【MySQL】DML数据操作语句和基本的DQL语句

目录 一、Mysql对数据的增删改 1. 增加数据 2. 修改数据&#xff08;UPDATE语句&#xff09; 3. 删除 3.1 delete、truncate、drop区别 二、DQL语言&#xff08;重点&#xff09; 1. 单表查询 1.1 最简单的查询 1.2 从表中获取数据 1.3 字段名起别名 1.4 添加字段 1…

深度学习——线性神经网络(一、线性回归)

目录 一、线性回归1.1 线性回归的基本元素1.1.1 术语介绍1.1.2 线性模型1.1.3 损失函数1.1.4 解析解1.1.5 随机梯度下降1.1.6 模型预测 1.2 正态分布与平方损失 因为线性神经网络篇幅比较长&#xff0c;就拆成几篇博客分开发布。目录序号保持连贯性。 一、线性回归 回归&#x…

Linux:深入理解冯诺依曼结构与操作系统

目录 1. 冯诺依曼体系结构 1.1 结构分析 1.2 存储结构分布图 2. 操作系统 2.1 概念 2.2 如何管理 2.3 什么是系统调用和库函数 1. 冯诺依曼体系结构 1.1 结构分析 不管是何种计算机&#xff0c;如个人笔记本电脑&#xff0c;服务器&#xff0c;都是遵循冯诺依曼结构。…

基于Springboot的在线订餐系统设计与实现(论文+源码)_kaic

摘 要 当今世界&#xff0c;互联网以及和互联网有关的行业都在不断的发展&#xff0c;也在持续走进人们的生活&#xff0c;在此趋势下人们对于通过互联网解决生活问题的需求愈来愈多&#xff0c;本文考虑到了这些情况后做出了该订餐系统。 本系统选择了MySQL作为主要存储单元…

深入探讨Windows 11专业版与Windows 11专业工作站版的差异

前言 深入探讨Windows 11专业版与Windows 11专业工作站版的差异&#xff0c;可以更全面地理解这两款操作系统版本面向的不同用户群体、硬件支持、性能特点以及应用场景&#xff0c;从而为专业用户和企业选择最合适的平台提供依据。 硬件支持与扩展能力 Windows 11专业版&…

Apache OFBiz SSRF漏洞CVE-2024-45507分析

Apache OFBiz介绍 Apache OFBiz 是一个功能丰富的开源电子商务平台&#xff0c;包含完整的商业解决方案&#xff0c;适用于多种行业。它提供了一套全面的服务&#xff0c;包括客户关系管理&#xff08;CRM&#xff09;、企业资源规划&#xff08;ERP&#xff09;、订单管理、产…

记录一次学习--委派攻击学习

目录 为什么要使用委派 什么账号可以使用委派 非约束性委派 这里有一张图 利用 流程 约束性委派 这里有一张图 如何利用 条件 具体流程 为什么要使用委派 这个是因为可能A服务需要B服务的支持&#xff0c;但是A服务的权限不可以使用B服务。然后这时就可以让域用户将…

OpenStack Yoga版安装笔记(十四)启动一个实例

1、官方文档 OpenStack Installation Guidehttps://docs.openstack.org/install-guide/ 本次安装是在Ubuntu 22.04上进行&#xff0c;基本按照OpenStack Installation Guide顺序执行&#xff0c;主要内容包括&#xff1a; 环境安装 &#xff08;已完成&#xff09;OpenStack…

OpenCV计算机视觉库

计算机视觉和图像处理 Tensorflow入门深度神经网络图像分类目标检测图像分割OpenCVPytorchNLP自然语言处理 OpenCV 一、OpenCV简介1.1 简介1.2 OpenCV部署1.3 OpenCV模块 二、OpenCV基本操作2.1 图像的基本操作2.1.1 图像的IO操作2.1.2 绘制几何图像2.1.3 获取并修改图像的像素…

无人机电力巡检:点亮电力巡检新视野!

一、无人机电力巡查的优势 提高巡检效率&#xff1a;无人机可以搭载高清摄像头、红外热像仪等先进设备&#xff0c;实时拍摄和传输图像&#xff0c;帮助巡检人员快速发现潜在问题&#xff0c;如电线破损、绝缘子污损、设备过热等&#xff0c;从而大大缩短了巡检周期。 降低人…

python-斐波那契词序列/最大回文乘积/求最大最小k个元素

一:斐波那契词序列题目描述 编写一个程序&#xff0c;生成斐波那契词序列的前n个元素。 斐波那契词序列是一个词序列&#xff0c;其中每个词是通过连接前两个词形成的。 它以斐波那契序列命名&#xff0c;因为它是以类似的方式创建的&#xff0c;但是我们不是加数字&#xff0c…