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

专门为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和ImageKnifeImageKnife.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()){// 这样就获取到了目标PixelMaplet 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.mzph.cn/news/763630.shtml

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

相关文章

新材料正在加速金属3D打印的应用步伐

在金属3D打印领域,材料性能是影响工件综合表现的关键因素,如强度、硬度、耐腐蚀性、抛光性能以及导热性能等,都与材料息息相关,好的材料是推动金属3D打印向更多领域应用的基础。 在这一背景下,上海毅速新材料推出的多款…

递增四元组

解法: 首先都可以想到dp[i]:第i个元素结尾的递增四元组有dp[i]个 然后发现有一组数据:2,3,6,1,5,8。会出现6结尾和5结尾的递增三元组,也就是未来的决策受过去影响,专业的说就是有后效性。需要强化约束条件&#xff0…

vue3+threejs新手从零开发卡牌游戏(三):尝试在场景中绘制一张卡牌

首先我们思考下,一张最简单的卡牌有哪些东西构成:卡牌样式和卡牌数据。一张卡牌有正面和背面,有名称、属性、种族、攻击力等数据,我们先不考虑数据,先尝试在场景中绘制一张卡牌出来。 一、寻找卡牌素材 为了简单我直…

变老特效怎么弄?分享3个软件体验!

变老特效怎么弄?分享3个软件体验! 当我们想要预览自己老去的模样,或者给照片增添一丝岁月的韵味时,变老特效成为了一个热门选择。那么,这种神奇的效果是如何实现的呢?又有哪些软件可以让我们轻松体验呢&am…

就业班 第二阶段 2401--3.18 day1 初识mysql

初识: 1、关系型数据库mysql、mariadb、sqlite 二维关系模型 2、非关系型数据库 redis、memcached sql 四个部分 DDL 数据库定义语言 创建数据库,创建用户,创建表 DML 数据库操作语言 增删改 DQL 数据库查询语言 查 DCL 数据库控制语言 授权 …

忘记密码找回流程请求拦截器-前端

目录 设置找回密码请求拦截器 1.相关参数 2.约定 代码实现 1. 实现思路 2. 实现代码 校园统一身份认证系统: 基于网络安全,找回密码、重新设置密码的流程和正常登录流程中密钥等请求头不一致。 设置找回密码请求拦截器 1.相关参数 clientId 应…

多线程实现

1.多线程:并发实现 主线程和子线程并行实现。 一个进程中有多个线程,可以同时进行多个任务。进程是系统分配的,线程的执行是由调度器决定的。 注意:线程开启不一定执行,由Cpu调度执行。 线程创建的三种方式&#xff…

HarmonyOS系统开发ArkTS常用组件文本输入及参数

TextInput文本输入组件,用于接收用户输入的文本内容。 1、TextInput组件的参数 TextInput(value?:{placeholder?: string|Resource , text?: string|Resource}) placeholder属性用于设置无输入时的提示文本text用于设置输入框当前的文本内容 Entry Component st…

20240316-2-协同过滤(collaborative filtering)

协同过滤(collaborative filtering) 直观解释 协同过滤是推荐算法中最常用的算法之一,它根据user与item的交互,发现item之间的相关性,或者发现user之间的相关性,进行推荐。比如你有位朋友看电影的爱好跟你类似,然后最…

【Review+预测】测试架构演进的曲折之路

文章目录 前言 一、“原始”阶段 二、“小打小闹”阶段 三、“小米加步枪”阶段 四、“摩托化部队”阶段 五、“骑兵连”阶段 六、“海军陆战队”阶段 七、“社区型组织”阶段 前言 近期公司的测试团队需要重新组织安排,本着谦虚谨慎的态度,我从…

代码随想录算法训练营 DAY 17 | 110.平衡二叉树 257.二叉树的所有路径 404.左叶子之和

110.平衡二叉树 平衡二叉树的定义:任何节点的左右子树高度差绝对值不超过1 空树也是AVL! 确定遍历顺序: 求高度用后序,求深度用前序。(取决于需不需要从下往上返回结果) 先判断它是不是平衡二叉树 如果是就返回 如…

【CVTE 一面凉经Ⅰ】循环依赖如何解决

目录 一.🦁 开始前的废话二. 🦁 什么是循环依赖?三. 🦁Spring 容器解决循环依赖的原理是什么?五. 🦁 三级缓存解决循环依赖的原理六. 🦁 由有参构造方法注入属性的循环依赖如何解决?七.&#x…

vue3通过el-cascader实现动态菜单切换页面

如果只有一级菜单只会显示一个按钮 <div style"width: 100%; margin-top: 10px; display: flex; align-items: center; border-bottom: 1px solid #ccc;"><template v-for"(menu, index) in cascaderData" :key"index"><el-casc…

整数和浮点数在内存中存储

整数在内存中的存储 整数的2进制表⽰⽅法有三种&#xff0c;即原码、反码和补码。 对于整形来说&#xff0c;数据存放内存中的其实是补码。 在计算机系统中&#xff0c;数值一律用补码来表示和存储。原因是&#xff0c;使用补码&#xff0c;可以使符号位和数值域统一处理&am…

DUSt3R:简化三维重建

3D 重建是从二维 (2D) 图像创建对象或场景的 3D 虚拟表示的任务&#xff0c;可用于模拟、可视化或本地化等多种目的。 它广泛应用于计算机视觉、机器人和虚拟现实&#xff08;VR&#xff09;等多个领域。 在基本设置中&#xff0c;3D 重建方法输入一对图像 I1 和 I2&#xff0c…

关于Java对接网络验证+实践小例子,简单易懂

一个简单的网络验证小例子&#xff0c;各位大佬勿喷 突发奇想&#xff0c;如果一位A友找你拿一份 Working Fruits&#xff0c;但是你不想这位A友把你辛苦劳作、熬夜加点写出的代码分享他或她的另外一位朋友B友&#xff0c;也许并不是很有价值的一个小作业而已&#xff0c;但是就…

数据结构:详解【栈和队列】的实现

目录 1. 栈1.1 栈的概念及结构1.2 栈的实现1.3 栈的功能1.4 栈的功能的实现1.5 完整代码 2. 队列2.1 队列的概念及结构2.2 队列的实现2.3 队列的功能2.4 队列的功能的实现2.5 完整代码 1. 栈 1.1 栈的概念及结构 栈&#xff1a;一种特殊的线性表&#xff0c;其只允许在固定的…

模拟B\S服务器(扩展知识点)

3.2 模拟B\S服务器(扩展知识点) 模拟网站服务器&#xff0c;使用浏览器访问自己编写的服务端程序&#xff0c;查看网页效果。 案例分析 准备页面数据&#xff0c;web文件夹。 复制到我们Module中&#xff0c;比如复制到day08中 我们模拟服务器端&#xff0c;ServerSocket类…

SpringCloud Alibaba实战和源码(8)OpenFeign使用

1、 使用Feign实现远程HTTP调用 1.1、常见HTTP客户端 HttpClient HttpClient 是 Apache Jakarta Common 下的子项目&#xff0c;用来提供高效的、最新的、功能丰富的支持 Http 协 议的客户端编程工具包&#xff0c;并且它支持 HTTP 协议最新版本和建议。HttpClient 相比传统 J…

RN开发搬砖经验之—处理“Duplicate class com.github.barteksc.pdfviewer“

问题信息 Duplicate class com.github.barteksc.pdfviewer.PDFView found in modules jetified-AndroidPdfViewer-3.1.0-beta.3-runtime (com.github.TalbotGooday:AndroidPdfViewer:3.1.0-beta.3) and jetified-android-pdf-viewer-2.8.2-runtime (com.github.barteksc:andro…