鸿蒙开发案例:【图像加载缓存库ImageKnife】

news2024/11/14 14:36:17

专门为OpenHarmony打造的一款图像加载缓存库,致力于更高效、更轻便、更简单。

简介

OpenHarmony的自研版本:

  • 支持内存缓存,使用LRUCache算法,对图片数据进行内存缓存。
  • 支持磁盘缓存,对于下载图片会保存一份至磁盘当中。
  • 支持进行图片变换: 支持图像像素源图片变换效果。
  • 支持用户配置参数使用:( 例如:配置是否开启一级内存缓存,配置磁盘缓存策略,配置仅使用缓存加载数据,配置图片变换效果,配置占位图,配置加载失败占位图等)。
  • 推荐使用ImageKnifeComponent组件配合ImageKnifeOption参数来实现功能。
  • 支持用户自定义配置实现能力参考ImageKnifeComponent组件中对于入参ImageKnifeOption的处理。

下载安装

ohpm install @ohos/imageknife

使用说明

1.依赖配置

在entry\src\main\ets\entryability\EntryAbility.ts中做如下配置初始化全局ImageKnife实例:

import UIAbility from '@ohos.app.ability.UIAbility';
import window from '@ohos.window';
import { ImageKnife } from '@ohos/imageknife'

export default class EntryAbility extends UIAbility {
  onWindowStageCreate(windowStage: window.WindowStage) {
    windowStage.loadContent('pages/Index', (err, data) => {
    });
    // 初始化全局ImageKnife 
    ImageKnife.with(this.context);
  	// 后续访问ImageKnife请通过:ImageKnifeGlobal.getInstance().getImageKnife()方式
  }
}

2.加载普通图片

接下来我们来写个简单实例看看:

import { ImageKnifeComponent, ImageKnifeOption } from '@ohos/imageknife'

@Entry
@Component
struct Index {
  @State message: string = 'Hello World'
  @State option: ImageKnifeOption = {
    loadSrc: $r('app.media.icon')
  }

  build() {
      Row() {
        Column() {
          Text(this.message)
            .fontSize(50)
            .fontWeight(FontWeight.Bold)
          ImageKnifeComponent({ imageKnifeOption: this.option })
            .width(300)
            .height(300)
        }.width('100%')
      }.height('100%')
  }
}

非常简单,仅需定义一个ImageKnifeOption数据对象,然后在你需要的UI位置,加入ImageKnifeComponent自定义组件就可以加载出一张图像了。

3.加载SVG图片

加载svg其实和普通流程没有区别,只要将 loadSrc: $r('app.media.jpgSample'), 改成一张 loadSrc: $r('app.media.svgSample'), svg类型图片即可。

4.加载GIF图片

加载GIF其实和普通流程也没有区别只要将 loadSrc: $r('app.media.jpgSample'), 改成一张 loadSrc: $r('app.media.gifSample'), GIF图片即可。

5.自定义Key

因为通常改变标识符比较困难或者根本不可能,所以ImageKnife也提供了 签名 API 来混合(你可以控制的)额外数据到你的缓存键中。 签名(signature)适用于媒体内容,也适用于你可以自行维护的一些版本元数据。

将签名传入加载请求

imageKnifeOption = {
                loadSrc: 'https://aahyhy.oss-cn-beijing.aliyuncs.com/blue.jpg',
                signature: new ObjectKey(new Date().getTime().toString())
              }

详细样例请参考SignatureTestPage文件

代码示例

进阶使用

如果简单的加载一张图像无法满足需求,我们可以看看ImageKnifeOption这个类提供了哪些扩展能力。

ImageKnifeOption参数列表

参数名称入参内容功能简介
loadSrcstringPixelMap\Resource
mainScaleTypeScaleType设置主图展示样式(可选)
strategyDiskStrategy设置磁盘缓存策略(可选)
dontAnimateFlagbooleangif加载展示一帧(可选)
placeholderSrcPixelMapResource占位图数据源
placeholderScaleTypeScaleType设置占位图展示样式(可选)
errorholderSrcPixelMapResource错误占位图数据源
errorholderSrcScaleTypeScaleType设置失败占位图展示样式(可选)
retryholderSrcPixelMapResource重试占位图数据源
retryholderScaleTypeScaleType设置重试占位图展示样式(可选)
thumbSizeMultipliernumber 范围(0,1]设置缩略图占比(可选)
thumbSizeDelaynumber设置缩略图展示时间(可选)
thumbSizeMultiplierScaleTypeScaleType设置缩略图展示样式(可选)
displayProgressboolean设置是否展示下载进度条(可选)
canRetryClickboolean设置重试图层是否点击重试(可选)
onlyRetrieveFromCacheboolean仅使用缓存加载数据(可选)
isCacheableboolean是否开启一级内存缓存(可选)
gif{ // 返回一周期动画gif消耗的时间 loopFinish?: (loopTime?) => void // gif播放速率相关 speedFactory?: number // 直接展示gif第几帧数据 seekTo?: number }GIF播放控制能力(可选)
transformationBaseTransform单个变换(可选)
transformationsArray多个变换,目前仅支持单个变换(可选)
allCacheInfoCallbackIAllCacheInfoCallback输出缓存相关内容和信息(可选)
signatureObjectKey自定key(可选)
drawLifeCycleIDrawLifeCycle用户自定义实现绘制方案(可选)
imageSmoothingEnabledboolean抗锯齿是否开启属性配置,设置为false时,imageSmoothingQuality失效
imageSmoothingQualityAntiAliasing抗锯齿属性配置

其他参数只需要在ImageKnifeOption对象上按需添加即可。

这里我们着重讲一下自定义实现绘制方案。为了增强绘制扩展能力,目前ImageKnifeComponent使用了Canvas的渲染能力作为基础。在此之上为了抽象组件绘制表达。我将图像的状态使用了 IDrawLifeCycle绘制生命周期进行表达

大致流程 展示占位图->展示网络加载进度->展示缩略图->展示主图->展示重试图层->展示失败占位图

ImageKnifeComponent内部,责任链实现。 用户参数设置->全局参数设置->自定义组件内部设置

采用责任链的好处是,用户可以通过自定义绘制,重新绘制图层。如果不想绘制也可以通过预制回调获取绘制流程信息。

场景1:默认的展示不满足需求,需要加个圆角效果。

代码如下:

import { ImageKnifeComponent } from '@ohos/imageknife'
import { ImageKnifeOption } from '@ohos/imageknife'
import { ImageKnifeDrawFactory } from '@ohos/imageknife'

@Entry
@Component
struct Index {
  @State imageKnifeOption1: ImageKnifeOption = { 
      // 加载一张本地的jpg资源(必选)
      loadSrc: $r('app.media.jpgSample'),
      // 占位图使用本地资源icon_loading(可选)
      placeholderSrc: $r('app.media.icon_loading'),
      // 失败占位图使用本地资源icon_failed(可选)
      errorholderSrc: $r('app.media.icon_failed'),
      // 绘制圆角30,边框5,边框"#ff00ff".用户自定义绘制(可选)
      drawLifeCycle:ImageKnifeDrawFactory.createRoundLifeCycle(5,"#ff00ff",30)
    };
        
    build(){
        Scroll() {
          Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
            ImageKnifeComponent({ imageKnifeOption: this.imageKnifeOption1 })
            .width(300) 
            .height(300)
          }
        }
        .width('100%')
        .height('100%')
    }
}

ImageKnifeDrawFactory.createRoundLifeCycle(5,"#ff00ff",30) 我们深入查看源码可以发现,实际上是对IDrawLifeCycle接口的部分实现,这里我介绍一下IDrawLifeCycle。

IDrawLifeCycle的返回值代表事件是否被消费,如果被消费接下来组件内部就不会处理,如果没被消费就会传递到下一个使用者。目前消费流程(用户自定义-> 全局配置定义->组件内部默认定义) *

所以我们在当数据是一张PixelMap的时候(目前jpg png bmp webp svg返回的都是PixelMap,gif返回GIFFrame数组),我们返回了true。消费了事件,代表这个绘制流程用户自定义完成。

由于IDrawLifeCycle实现较为冗长,我们封装了ImageKnifeDrawFactory工厂,提供了网络下载百分比效果、圆角、椭圆添加边框等能力。下面我们就再看看使用工厂封装之后的场景代码。

场景2: 网络下载百分比效果展示

当进行加载网络图片时,可能需要展示网络下载百分比动画。但是默认的动画又不能满足需求,这个时候我们就需要自定义网络下载百分比效果。代码如下:

import UIAbility from '@ohos.app.ability.UIAbility';
import window from '@ohos.window';
import { ImageKnifeGlobal,ImageKnife,ImageKnifeDrawFactory,LogUtil } from '@ohos/imageknife'
import abilityAccessCtrl,{Permissions} from '@ohos.abilityAccessCtrl';
export default class EntryAbility extends UIAbility {
    onWindowStageCreate(windowStage: window.WindowStage) {
        //.. 删除不必要代码
        windowStage.loadContent('pages/index', (err, data) => {
        });
       	// 初始化ImageKnifeGlobal和ImageKnife
        ImageKnife.with(this.context);
        // 全局配置网络加载进度条 使用ImageKnifeGlobal.getInstance().getImageKnife()访问ImageKnife
ImageKnifeGlobal.getInstance().getImageKnife().setDefaultLifeCycle(ImageKnifeDrawFactory.createProgressLifeCycle("#10a5ff", 0.5))
    }
}

这里大家可能会问,为什么会将这个IDrawLifeCycle放在AbilityStage里面实现?

这是因为网络下载百分比进度很多时候都是全局通用,如果有需要全局配置的自定义展示方案。推荐在AbilityStage里面,往ImageKnife的setDefaultLifeCycle函数中注入,即可将ImageKnifeComponent中的默认绘制方案替换。

在这里我们实现的效果如下图所示。

高级用法

以上简单使用和进阶使用都是经过一层自定义组件封装之后形成的,RequestOption封装成了ImageKnifeOption,绘制部分封装成了自定义组件ImageKnifeComponent。

如果用户其实并不关心绘制部分,或者说想用自己的通用方案对自定义组件ImageKnifeComponent重构都是可以的。

下面我们会着重指导用户如何复用图片加载逻辑,重构自定义组件ImageKnifeComponent。

首先我们先看看RequestOption构建的内容,如下所示:

数据加载

RequestOption构建:

请查阅下文接口内容:[RequestOption接口方法]

了解了RequestOption的参数内容后,我们可以参考ImageKnifeComponent组件代码进行分析。

imageKnifeExecute()函数入口,首先我们需要构建一个RequestOption对象,let request = new RequestOption(), 接下来就是按需配置request对象的内容,最后使用 ImageKnifeGlobal.getInstance().getImageKnife()?.call(request)发送request执行任务即可。

是不是很简单,而其实最重要的内容是就是: 按需配置request对象的内容 为了更好理解,我举例说明一下:

场景一: 简单加载一张图片
let request = new RequestOption();
// (必传)
request.load("图片url")
  // (可选 整个request监听回调)
	.addListener({callback:(err:BusinessError|string, data:ImageKnifeData) => {
	// data 是ImageKnifeData对象
	if(data.isPixelMap()){
	// 这样就获取到了目标PixelMap
	let pixelmap = data.drawPixleMap.imagePixelMap;
	}
    return false;
  })
 
  let compSize:Size = {
    width: this.currentWidth,
    height:this.currentHeight
  }
  // (必传)这里setImageViewSize函数必传组件大小,因为涉及到图片变换效果都需要适配图像源和组件大小
 request.setImageViewSize(compSize)
 // 最后使用ImageKnife的call函数调用request即可
 let imageKnife:ImageKnife|undefined = ImageKnifeGlobal.getInstance().getImageKnife();
 if(imageKnife != undefined){
 	imageKnife.call(request)
 }

其他场景,可以按需加载

比如我需要配置 占位图 只需要 在request对象创建好之后,调用 placeholder 函数即可

request.placeholder(this.imageKnifeOption.placeholderSrc, (data) => {
  console.log('request.placeholder callback')
  this.displayPlaceholder(data)
})

再比如 我对缓存配置有要求,我要禁用内存缓存,调用 skipMemoryCache 函数即可

request.skipMemoryCache(true)

这里只是简单介绍部分使用,更多的内容请参考 按需加载 原则,并且可以参考ImageKnifeComponent源码或者根据文档自行探索实现。

接口说明

RequestOption用户配置参数

方法名入参接口描述
load(src: stringPixelMapResource)src:stringPixelMapResource用户加载图片源
setImageViewSize(imageSize: { width: number, height: number })imageSize:{width: number, height: number }传入显示图片组件的大小,变换的时候需要作为参考
diskCacheStrategy(strategy: DiskStrategy)strategy:DiskStrategy配置磁盘缓存策略 NONE SOURCE RESULT ALL AUTOMATIC
placeholder(src: PixelMapResource, func?: AsyncSuccess)src: PixelMapResource, func?: AsyncSuccess占位图,占位图回调数据ImageKnifeData
errorholder(src: PixelMapResource, func?: AsyncSuccess)src: PixelMapResource, func?: AsyncSuccess错误占位图,错误占位图回调数据ImageKnifeData
retryholder(src: PixelMapResource, func?: AsyncSuccess)src: PixelMapResource, func?: AsyncSuccess重试占位图,重试占位图回调数据ImageKnifeData
addListener(func: AsyncCallback)func: AsyncCallback配置整个监听回调,数据正常加载返回,加载失败返回错误信息
thumbnail(sizeMultiplier:number, func?: AsyncSuccess)sizeMultiplier:number, func?: AsyncSuccess设置缩略图比例,缩略图返回后,加载并展示缩略图
addProgressListener(func?: AsyncSuccess)func?: AsyncSuccess设置网络下载百分比监听,返回数据加载百分比数值
addAllCacheInfoCallback(func: IAllCacheInfoCallback)func: IAllCacheInfoCallback设置获取所有缓存信息监听
skipMemoryCache(skip: boolean)skip: boolean配置是否跳过内存缓存
retrieveDataFromCache(flag: boolean)flag: boolean配置仅从缓存中加载数据
signatureObjectKey自定义key

同时支持[图片变换相关]接口。

ImageKnife 启动器/门面类

方法名入参接口描述
call(request: RequestOption)request: RequestOption根据用户配置参数具体执行加载流程
preload(request: RequestOption)request: RequestOption根据用户配置参数具体执行预加载流程
pauseRequests()全局暂停请求
resumeRequests()全局恢复暂停

缓存策略相关

使用方法类型策略描述
request.diskCacheStrategy(new ALL())ALL表示既缓存原始图片,也缓存转换过后的图片
request.diskCacheStrategy(new AUTOMATIC())AUTOMATIC表示尝试对本地和远程图片使用适合的策略
request.diskCacheStrategy(new DATA())DATA表示只缓存原始图片
request.diskCacheStrategy(new NONE())NONE表示不缓存任何内容
request.diskCacheStrategy(new RESOURCE())RESOURCE表示只缓存转换过后的图片

AntiAliasing类型展示效果

使用方法类型策略描述
AntiAliasing.FIT_HIGHString图像抗锯齿设置为高画质
AntiAliasing.FIT_MEDIUMString图像抗锯齿设置为中画质
AntiAliasing.FIT_LOWString图像抗锯齿设置为低画质

ScaleType类型展示效果

使用方法类型策略描述
ScaleType.FIT_STARTint图像位于用户设置组件左上角显示,图像会缩放至全部展示
ScaleType.FIT_ENDint图像位于用户设置组件右下角显示,图像会缩放至全部展示
ScaleType.FIT_CENTERint图像位于用户设置组件居中,图像会缩放至全部展示
ScaleType.CENTERint图像居中展示,不缩放
ScaleType.CENTER_CROPint图像的宽高长度,短的部分缩放至组件大小,超出的全部裁剪
ScaleType.FIT_XYint图像拉伸至组件大小
ScaleType.CENTER_INSIDEint如果图像大于组件则执行FIT_CENTER,小于组件则CENTER
ScaleType.NONEint如果不想适配,直接展示原图大小

图片变换相关

使用方法类型相关描述
request.centerCrop()CenterCrop可以根据图片文件,目标显示大小,进行对应centerCrop
request.centerInside()CenterInside可以根据图片文件,目标显示大小,进行对应centerInside
request.fitCenter()FitCenter可以根据图片文件,目标显示大小,进行对应fitCenter
request.blur()BlurTransformation模糊处理(图片分辨率较大建议传递第二个参数将图片进行缩小)
request.brightnessFilter()BrightnessFilterTransformation亮度滤波器
request.contrastFilter()ContrastFilterTransformation对比度滤波器
request.cropCircle()CropCircleTransformation圆形剪裁显示
request.cropCircleWithBorder()CropCircleWithBorderTransformation圆环展示
request.cropSquare()CropSquareTransformation正方形剪裁
request.crop()CropTransformation自定义矩形剪裁
request.grayscale()GrayscaleTransformation灰度级转换
request.invertFilter()InvertFilterTransformation反转滤波器
request.pixelationFilter()PixelationFilterTransformation像素化滤波器
request.rotateImage()RotateImageTransformation图片旋转
request.roundedCorners()RoundedCornersTransformation圆角剪裁
request.sepiaFilter()SepiaFilterTransformation乌墨色滤波器
request.sketchFilter()SketchFilterTransformation素描滤波器
request.mask()MaskTransformation遮罩
request.swirlFilter()SwirlFilterTransformation扭曲滤波器
request.kuwaharaFilter()KuwaharaFilterTransform桑原滤波器
request.toonFilter()ToonFilterTransform动画滤波器
request.vignetteFilter()VignetteFilterTransform装饰滤波器

setLruCacheSize

setLruCacheSize(size: number,memory:number): void

设置图片文件缓存的大小上限,size单位为张数,memory单位为字节,提升再次加载同源图片的加载速度,特别是对网络图源会有较明显提升。 如果不设置则默认为100张,100MB。缓存采用内置的LRU策略。 size为0则代表不限制缓存张数,memory为0则代表不限制缓存大小。 建议根据应用实际需求,设置合理缓存上限,数字过大可能导致内存占用过高,可能导致OOM异常。

参数:

参数名类型必填说明
sizenumber图片文件的缓存张数,单位为张。只支持正整数,0
memorynumber图片文件的缓存大小,单位为字节。只支持正数,0

示例:

//EntryAbility.ets
import { InitImageKnife } from '...imageknife'
export default class EntryAbility extends UIAbility {
  onWindowStageCreate(windowStage: window.WindowStage) { 
    InitImageKnife.init(this.context);
    let imageKnife: ImageKnife | undefined = ImageKnifeGlobal.getInstance().getImageKnife()
    if (imageKnife != undefined) {
      //设置全局内存缓存大小张数
      imageKnife.setLruCacheSize(100, 100 * 1204 * 1024)
    }
  }
}

约束与限制

在下述版本验证通过: DevEco Studio 4.1(4.1.3.520)--SDK:API11( 4.1.0.63) DevEco Studio 4.1(4.1.3.418)--SDK:API11( 4.1.0.56) DevEco Studio 4.1(4.1.3.322)--SDK:API11( 4.1.0.36) DevEco Studio 4.0(4.0.3.700)--SDK:API10( 4.0.10.15)

HSP场景适配:

在使用ImageKnifeComponent进行加载图片时, 提供的ImageKnifeOption配置类新增了可选参数context, 在HSP场景下需要传入正确的context, 才能保证三方库后续正确获取Resource资源。

在使用RquestOption进行加载图片时, 提供的RquestOption配置类新增了接口setModuleContext(moduleCtx:common.UIAbilityContext), 在HSP场景下需要传入正确的context, 才能保证三方库后续正确获取Resource资源。

非HSP场景不影响原功能, ImageKnifeOption配置类新增的可选参数context可以不传, RquestOption配置类新增的接口可以不调用。

更多鸿蒙开发知识已经更新在gitee.com/li-shizhen-skin/harmony-os/blob/master/README.md前往参考。

HarmonyOS与OpenHarmony技术路线曲线图1.png

遗留问题

1.目前只支持一种图片变换效果。

2.目前svg和gif动图不支持变换效果。

补充说明

SVG标签说明

使用版本为(SVG)1.1,当前支持的标签列表有:

  • a
  • circla
  • clipPath
  • defs
  • ellipse
  • feBlend
  • feColorMatrix
  • feComposite
  • feDiffuseLighting
  • feDisplacementMap
  • feDistantLight
  • feFlood
  • feGaussianBlur
  • feImage
  • feMorphology
  • feOffset
  • fePointLight
  • feSpecularLighting
  • feSpotLight
  • feTurbulence
  • filter
  • g
  • image
  • line
  • linearGradient
  • mask
  • path
  • pattern
  • polygon
  • polyline
  • radialGradient
  • rect
  • stop
  • svg
  • text
  • textPath
  • tspan

鸿蒙值得开发者入行

为什么这么说?市场是决定人力需求的,数据说话最管用:

1、鸿蒙其全栈自研,头部大厂商都陆续加入合作开发鸿蒙原生应用——人才需求上涨

2、鸿蒙作为新系统、新技术,而现在市面上技术人才少——高薪招聘开启

3、鸿蒙1+8+N生态,不仅只有应用开发;还有车载、数码、智能家居、家电等——就业范围广

4、纯血鸿蒙,目前没有多少人熟悉。都处于0基础同一起跑线——无行业内卷

开发者最需要什么?岗位多、薪资高、不内卷、行业竞争低。而当下的鸿蒙恰恰符合要求。

那么这么好的鸿蒙岗位,应聘要求都很高吧?其实不然鸿蒙作为新出的独立系统,其源头上大家都处于同一水平线上,一开始的技术要求都不会很高,毕竟面试官也是刚起步学习。招聘要求示例:

从信息看出,几乎应职要求是对标有开发经验的人群。可以说鸿蒙对开发者非常友好,尽管上面没提鸿蒙要求,但是面试都会筛选具有鸿蒙开发技能的人。我们程序员都知道学习开发技术,最先是从语言学起,鸿蒙语言有TS、ArkTS等语法,那么除了这些基础知识之外,其核心技术点有那些呢?下面就用一张整理出的鸿蒙学习路线图表示:

从上面的OpenHarmony技术梳理来看,鸿蒙的学习内容也是很多的。现在全网的鸿蒙学习文档也是非常的少,下面推荐一些:完整内容可在头像页保存,或这qr23.cn/AKFP8k甲助力

内容包含:

  • ArkTS
  • 声明式ArkUI
  • 多媒体
  • 通信问题
  • 系统移植
  • 系统裁剪
  • FW层的原理
  • 各种开发调试工具
  • 智能设备开发
  • 分布式开发等等。

这些就是对往后开发者的前景分享,希望大家多多点赞关注喔!

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

第十四届蓝桥杯JavaB组省赛真题 - 阶乘求和

/ 10^9考虑前九位,% 10^9保留后9位 解题思路: 求获取结果的后九位数字,需要对10^9取余,因为202320232023这个数字的阶乘太大,必须要减少计算量,因为当一个整数乘以10^9后对其取余,那么结果都为0。 所以我…

掌握C语言结构体,开启编程新世界

✨✨欢迎👍👍点赞☕️☕️收藏✍✍评论 个人主页:秋邱博客 所属栏目:C语言 (感谢您的光临,您的光临蓬荜生辉) 前言 前面我们也涉及到了结构体的讲解,但是只是粗略的讲了一下。 接下…

网络编程:包头分析

一、以太网头 以太网中封装了源mac地址以及目的mac地址,还有ip类型,以太网又称为mac头 0X0800 只接收发往本机的mac的ipv4类型的数据帧 0X0806 只接收发往本机的ARP类型的数据帧 0x8035 只接受发往本机的RARP类型的数据帧 0X0003 接收发往本机的MAC所…

田路分离数据的

因为农机大部分时间是在田地工作,所以大多数农机轨迹样本存在数据分布不平衡的问题,既田地数据多,道路数据少。因为用于分类的大多数机器学习算法都是围绕每个类别的样本数量均相等的假设来设计的。这导致模型的预测性能较差,特别…

Angular进阶之八: Angular Animation在项目中的实践经验

使用 Angular 进行项目开发的程序员应该都很熟悉 Angular Animation。这是一个 Angular 原生的动画库,它可以替代或者辅助完成原本需要使用 css 的动画功能。 Angular 在国内的运用是很有限的,可借鉴的文档并不很丰富。尤其对于 Angular 动画模块的应用…

[数据结构]堆

一、堆是什么? 堆是一种完全二叉树 完全二叉树的定义:完全二叉树的形式是指除了最后一层之外,其他所有层的结点都是满的,而最后一层的所有结点都靠左边。​​​​​​,从左到右连续。 教材上定义如下: 若设二叉树的…

纹波和噪声有啥区别(一)

首先要知道的是他们都是在电源输出中出现的信号波动,但两者存在明显的区别。 一,纹波的产生 电源纹波是指电源输出时,叠加在稳定的直流电源上的交流成分。 这种波动主要是由于电源自身的开关、PWM 调节等因素引起的,其频率一般…

Javaweb的学习21_CSS_属性

CSS的属性 (常用)属性: 1. 字体、文本 font-size:字体大小 color:文本颜色 text-align:文本的对齐方式 line-height:行高 2. 背景 background:是个复合属性 3. 边框 border:设置边框&#xff0c…

1升级powershell后才能安装WSL2--最后安装linux--Ubuntu 22.04.3 LTS

视频 https://www.bilibili.com/video/BV1uH4y1W7UX查看电脑本版 步骤1:使用 Winget 方式安装 PowerShell 查看是否能更新PowerShell– winget search Microsoft.PowerShell查看结果为 名称 ID 版本 源 ----------------------------…

HTML小游戏27 - Chuck Chicken 魔法蛋网页游戏(附完整源码)

💂 网站推荐:【神级源码资源网】【摸鱼小游戏】 【工具大全】🤟 基于Web端打造的:👉【轻量化工具创作平台】💅 想寻找共同学习交流、摸鱼划水的小伙伴,请点击【学习交流群】 本节教程我会带大家使用 HTML 、…

【Kafka系列】Kafka事务一般在什么场景下使用呢

面试官:听说你精通Kafka,那我就考考你吧 面试官:不用慌尽管说,错了也没关系😊。。。 以【面试官面试】的形式来分享技术,本期是《Kafka系列》,感兴趣就关注我吧❤️ 面试官:生产者重…

G1和ZGC垃圾回收器学习

前言 ​ 随着JDK17的占有率不断升高和SpringBoot3最低支持JDk17,JDK17很大概率会成为大家后续升级的一个选择,而JDK17上最重要的垃圾回收器G1和ZGC,也就显得格外重要。大家提前了解或者学习一下肯定是有用的。 ​ 本篇文章也默认大家了解一…

【linux】进程地址空间(进程三)

目录 快速了解:引入最基本的理解:细节:如何理解地址空间:a.什么是划分区域:b.地址空间的理解: 为什么要有进程空间?进一步理解页表与写时拷贝: 快速了解: 先来看这样一段…

docker入门(九)—— docker网络详细介绍

docker 网络 准备工作&#xff1a;清空所有镜像和容器 docker rm -f $(docker ps -aq) docker rmi -f $(docker images -aq)docker0 网络 查看本地网络 ip addr[rootiZbp15293q8kgzhur7n6kvZ /]# ip addr# 本地回环网络 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc…

jmeter接口导入方式

curl直接导入 1、操作页面后&#xff0c;F12查看接口&#xff0c;右击接口-copy-copy as cURL 2、jmeter 工具-import from cURL&#xff0c;粘贴上面复制的curl 根据接口文档导入 1、接口文档示例如下&#xff1a; Path&#xff1a; /api/jobs/xps/exec Method&#xf…

3d画线生成模型之后最大化找不到---模大狮模型网

当你在3D建模软件中画线生成模型后&#xff0c;如果最大化找不到该模型&#xff0c;可能是因为以下几种情况导致&#xff1a; 模型位置偏移&#xff1a; 可能你在绘制线条时&#xff0c;将模型画在了视图界面之外&#xff0c;导致最大化时无法看到。尝试平移或旋转模型&#x…

东方博宜 1449. 求满足条件的数的和

东方博宜 1449. 求满足条件的数的和 这道题我苦想了很久&#xff0c;觉得2个及2个以上很难解决&#xff0c;但是后面发现&#xff0c;可以用一个变量记录次数&#xff0c;次数大于等于2就好了。 #include<iostream> using namespace std; int main() {int n ;cin >…

企业用大模型如何更具「效价比」?百度智能云发布5款大模型新品

服务8万企业用户&#xff0c;累计帮助用户精调1.3万个大模型&#xff0c;帮助用户开发出16万个大模型应用&#xff0c;自2023年12月以来百度智能云千帆大模型平台API日调用量环比增长97%...从一年前国内大模型平台的“开路先锋”到如今的大模型“超级工厂”&#xff0c;百度智能…

革新水库大坝监测:传统软件与云平台之比较

在水库大坝的监测管理领域&#xff0c;传统监测软件虽然曾发挥了重要作用&#xff0c;但在多方面显示出了其局限性。传统解决方案通常伴随着高昂的运维成本&#xff0c;需要大量的硬件支持和人员维护&#xff0c;且软件整合和升级困难&#xff0c;限制了其灵活性和扩展性。 点击…

类对象的初始化过程与方法

类初始化过程与方法 一、类对象的初始化过程 1.初始化的过程 &#xff08;1&#xff09;对象在实例化的时候需要调用构造函数&#xff0c;如果对应的构造函数调用不了&#xff0c;这个对象是没有办法实例化的。 &#xff08;2&#xff09;构造函数的执行&#xff0c;是在内…