ImageKnife是一款图像加载缓存库,主要功能特性如下:

●支持内存缓存,使用LRUCache算法,对图片数据进行内存缓存。

●支持磁盘缓存,对于下载图片会保存一份至磁盘当中。

●支持进行图片变换:支持图像像素源图片变换效果。

●支持用户配置参数使用:(例如:配置是否开启一级内存缓存,配置磁盘缓存策略,配置仅使用缓存加载数据,配置图片变换效果,配置占位图,配置加载失败占位图等)。

更多细节请访问源码仓库地址:https://gitee.com/openharmony-tpc/ImageKnife

背景说明

早期ImageKnife三方库在实现渲染部分的时候,使用的是image组件来展示图片的。由于image组件其实是一个完整的集加载解析和图片展示的组件,渲染的模式只能通过配置固定参数进行,面对复杂的需求场景,可能会出现扩展性不够的情况。

现在随着时间的推移渲染组件又多了一位重量级选手Canvas组件。可以通过2个组件渲染层的能力对比进行判断渲染层最终交由哪个组件展示。

如果想了解更多ImageKnife的背景知识,可以点击链接查看之前的文章介绍:

旧版本ImageKnife加载流程介绍

https://developer.huawei.com/consumer/cn/forum/topic/0203864555891240375?fid=0101587866109860105

组件选型,能力对比

首先我们来看看Image组件和Canvas组件对于渲染这一块的支持情况。

从上表我们可以看出:

Image组件虽然支持了PixelMap的绘制,但是基本没有绘制控制能力,而且扩展性能力也比较弱,并且渲染过程不可见,也无法对绘制内容进行更多操作。

而Canvas组件属于更加底层的渲染组件,可以完美地控制绘制内容,并且渲染过程可见,符合了开发者对于扩展性要求较高的定制场景。

重构前后能力对比

重构完成的内容

1. 使用canvas组件替代Image组件进行渲染展示图片。

2. 所有图像数据在渲染层都转换为PixelMap,方便统一管理和扩展。

3. 所有回调节点,统一抽象成接口,方便后续进行扩展,提高代码可维护性。

4. 所有的回调节点绘制的实现,都采用了责任链模式,提高了自定义绘制扩展能力。

5. 将部分通用方法封装成工厂方法,减少开发者代码量。

6. 通用方法从配置参数剥离,可采用链式调用方式使用这些方法。

7. 为了支持列表ImageKnifeOption参数使用@LinkObject修饰,同时ImageKnifeOption类型被@Observed修饰继承,不可被继承。

重构中比较重要的点

点1:回调接口抽象为IDrawLifeCycle接口

渲染绘制是主线程才能操作。因此我们可以对渲染顺序进行了梳理,大致流程:展示占位图->展示网络加载进度->展示缩略图->展示主图->展示重试图层->展示失败占位图

这里每个蓝色的小方格都代表着一个数据返回的回调接口,我们需要在这个回调接口,处理接下来内容渲染的展示操作。因为每个回调的流程是固定的,有点像生命周期的流程。所以我这边抽象成接口IDrawLifeCycle绘制生命周期进行表达。这其实也是为了后面扩展做了准备。

点2:绘制实现采用责任链模式

我们支持了用户配置自定义绘制和全局配置自定义绘制的能力。采用了责任链模式实现,用户参数设置->全局参数设置->自定义组件内部设置。这样设计的好处就是保留了用户扩展的能力,用户可以参与自定义绘制。

点3:提供了ImageKnifeDrawFactory工厂类

在开发者需要进行自定义绘制时,必须实现IDrawLifeCycle的6个接口。为了简化开发者操作,这里提供了ImageKnifeDrawFactory工厂类。

ImageKnifeDrawFactory里面封装了圆角、椭圆、百分比下载等实现,简化用户操作。当然更多的需求,可以参考该工厂类自行扩展实现。

这里我们提供简单的场景示例:

场景1:一句代码,加个圆角效果

代码如下:

 1 import {ImageKnifeComponent} from '@ohos/imageknife'
2 import {ImageKnifeOption} from '@ohos/imageknife'
3 import {ImageKnifeDrawFactory} from '@ohos/imageknife'
4 @Entry
5 @Component
6 struct Index {
7 @State imageKnifeOption1: ImageKnifeOption =
8 { // 加载一张本地的png资源(必选)
9 loadSrc: $r('app.media.pngSample'),
10 // 主图的展示模式是 缩放至适合组件大小,并且在组件底部绘制
11 mainScaleType: ScaleType.FIT_END,
12 // 占位图使用本地资源icon_loading(可选)
13 placeholderSrc: $r('app.media.icon_loading'),
14 // 失败占位图使用本地资源icon_failed(可选)
15 errorholderSrc: $r('app.media.icon_failed'),
16 // 绘制圆角30,边框5,边框"#ff00ff".用户自定义绘制(可选)
17 drawLifeCycle:ImageKnifeDrawFactory.createRoundLifeCycle(5,"#ff00ff",30)
18 };
19 build() {
20 Scroll() {
21 Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
22 ImageKnifeComponent({ imageKnifeOption: this.imageKnifeOption1 })
23 .width(300) // 自定义组件已支持设置通用属性和事件,这里宽高设置放在链式调用中完成
24 .height(300)
25 }
26 }
27 .width('100%')
28 .height('100%')
29 }
30 }

场景2:全局配置网络下载百分比效果展示

仅需一句代码所有网络图片加载都能新增网络下载百分比效果展示。代码如下:

 1 import AbilityStage from '@ohos.application.Ability'
2 import { ImageKnife,ImageKnifeDrawFactory} from '@ohos/imageknife'
3
4 export default class EntryAbility extends Ability {
5 onCreate(want,launchParam) {
6 globalThis.ImageKnife = ImageKnife.with(this.context);
7 // 全局配置网络加载进度条
8 globalThis.ImageKnife.setDefaultLifeCycle(ImageKnifeDrawFactory.createProgressLifeCycle("#10a5ff", 0.5))
9 }
10 }

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

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

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

点4:通用属性方法和属性已经支持链式调用

比如下面的代码的宽高已经不用设置在ImageKnifeOption对象中了,直接在自定义组件下方链式调用设置即可。

 1 import {ImageKnifeComponent,ImageKnifeOption,ImageKnifeDrawFactory} from '@ohos/imageknife'
2 @Entry
3 @Component
4 struct Index {
5 @State imageKnifeOption1: ImageKnifeOption =
6 { // 加载一张本地的png资源(必选)
7 loadSrc: $r('app.media.pngSample'),
8 };
9 build() {
10 Scroll() {
11 Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
12 ImageKnifeComponent({ imageKnifeOption: this.imageKnifeOption1 })
13 .width(300) // 自定义组件已支持设置通用属性和事件,这里宽高设置放在链式调用中完成
14 .height(300)
15 }
16 }
17 .width('100%')
18 .height('100%')
19 }
20 }

点5:如何在列表使用

支持列表使用图片加载,只需要维护一个@State options:Array<ImageKnifeOption> = []

对象即可

 1 import {ImageKnifeOption,ImageKnifeComponent} from '@ohos/imageknife'
2 @Entry
3 @Component
4 struct BasicTestFeatureAbilityPage {
5 urls=[
6 "http://e.hiphotos.baidu.com/image/pic/item/a1ec08fa513d2697e542494057fbb2fb4316d81e.jpg",
7 "http://c.hiphotos.baidu.com/image/pic/item/30adcbef76094b36de8a2fe5a1cc7cd98d109d99.jpg",
8 "http://h.hiphotos.baidu.com/image/pic/item/7c1ed21b0ef41bd5f2c2a9e953da81cb39db3d1d.jpg",
9 "http://g.hiphotos.baidu.com/image/pic/item/55e736d12f2eb938d5277fd5d0628535e5dd6f4a.jpg",
10 "http://e.hiphotos.baidu.com/image/pic/item/4e4a20a4462309f7e41f5cfe760e0cf3d6cad6ee.jpg",
11 ]
12 @State options:Array<ImageKnifeOption> = []
13 aboutToAppear(){
14 this.options = this.urls.map((url)=>{
15 return {
16 loadSrc:url
17 }
18 })
19 console.log('this.options length ='+this.options.length)
20 }
21 build() {
22 Stack({ alignContent: Alignment.TopStart }) {
23 Column() {
24 List({ space: 20, initialIndex: 0 }) {
25 ForEach(this.options, (item) => {
26 ListItem() {
27 ImageKnifeComponent({imageKnifeOption:item}).width(300).height(300)
28 }
29 }, item => item.loadSrc)
30 }
31 .listDirection(Axis.Vertical) // 排列方向
32 .divider({ strokeWidth: 2, color: 0xFFFFFF, startMargin: 20, endMargin: 20 }) // 每行之间的分界线
33 .edgeEffect(EdgeEffect.None) // 滑动到边缘无效果
34 .chainAnimation(false) // 联动特效关闭
35 }.width('100%')
36 }.width('100%').height('100%').backgroundColor(0xDCDCDC).padding({ top: 5 })
37 }
38 }

渲染层重构的总结

综上可知,此次重构渲染层,一共新增了6个基础能力,适配了IDE最新版特性自定义组件可链式调用通用属性和方法,并且采用适合的设计模式保留了自定义组件绘制部分的拓展能力。展示了部分常用场景下使用代码的方式,帮助开发者更快上手开发。

最后在OpenHarmony不断推陈出新之际,三方库ImageKnife也应该激流勇进,不断地提升组件的实用性和适用性,为开发者创造一个良好的开发体验。

我们将会持续更新ImageKnife三方库,后续会切换成GPU来渲染图片变换能力,不断进行性能优化,提升ImageKnife三方库。

同时也欢迎开发者使用和提issue。

基于ArkUI框架开发-ImageKnife渲染层重构的更多相关文章

  1. 基于SSH框架开发的《高校大学生选课系统》的质量属性的实现

    基于SSH框架开发的<高校大学生选课系统>的质量属性的实现 对于可用性采取的是错误预防战术,即阻止错误演变为故障:在本系统主要体现在以下两个方面:(1)对于学生登录模块,由于初次登陆,学生 ...

  2. MapReduce教程(一)基于MapReduce框架开发<转>

    1 MapReduce编程 1.1 MapReduce简介 MapReduce是一种编程模型,用于大规模数据集(大于1TB)的并行运算,用于解决海量数据的计算问题. MapReduce分成了两个部分: ...

  3. PHP Yii框架开发——组织架构网站重构

    最近一段时间在维护公司的组织架构网站(Org),旧版网站只是用了xampp简单搭建了一套环境部署在了windows机器上,代码结构相对简单. 整个架构如下: 整个架构没有用到复杂的结构,class里放 ...

  4. 基于NopCommerce框架开发的微信小程序UrShop

    Urshop小程序商城 介绍 UrShop小程序商城 2.0发布啦,发布地址https://gitee.com/urselect/urshop UrShop 根据NopCommerce框架开发的,基于 ...

  5. web框架开发-Django模型层(1)之ORM简介和单表操作

    ORM简介 不需要使用pymysql的硬编码方式,在py文件中写sql语句,提供更简便,更上层的接口,数据迁移方便(有转换的引擎,方便迁移到不同的数据库平台)…(很多优点),缺点,因为多了转换环节,效 ...

  6. 基于ssh框架开发的购物系统的质量属性

    根据前面的博客,我们已经大致了解了ssh架构开发整体概念:Struts是一个实现了MVC模式的经典的框架:Hibernate是轻量级Java EE应用的持久层解决方案,以面向对象的方式提供了持久化类到 ...

  7. java基于ssm框架开发的公交查询系统源码公交系统源码公交路线查询项目有论文

    简介 java基于ssm的公交路线查询系统,用户可以查询公交站点公交车路线以及公交换乘方案,还可以查看公交车路线地图,以及该站点所有的公交车路线. 演示视频: https://www.ixigua.c ...

  8. java基于ssm框架开发的视频论坛网站源码

    简介 Java基于ssm开发的视频论坛网站,普通用户可以浏览视频搜索视频评论点赞收藏视频,关注用户.还可以浏览新闻,发布帖子到论坛. 演示视频 https://www.bilibili.com/vid ...

  9. 基于uniapp框架开发飞书小程序总结

    前期准备 飞书官方客户端文档:https://open.feishu.cn/document/home/intro 飞书官方工具资源文档:https://open.feishu.cn/document ...

  10. web框架开发-Django模型层(2)-多表操作

    很重要,都是精华 多表关系模型 一对一 一旦确定表关系是一对一,在两张表中的任意一张表中建立关联字段+Unique 一对多 一旦确定表关系是一对多,创建关联字段在多的表中 多对多 一旦确定表关系是多对 ...

随机推荐

  1. Qt开发技术:QtCharts(一)QtCharts基本介绍以及图表框架详解

    若该文为原创文章,未经允许不得转载原博主博客地址:https://blog.csdn.net/qq21497936原博主博客导航:https://blog.csdn.net/qq21497936/ar ...

  2. FFmpeg开发笔记(八):ffmpeg解码音频并使用SDL同步音频播放

    若该文为原创文章,未经允许不得转载原博主博客地址:https://blog.csdn.net/qq21497936原博主博客导航:https://blog.csdn.net/qq21497936/ar ...

  3. 项目实战:Qt数据分析处理平台(兼容各国产麒麟系统)(文件域字符串解析,上万文件批量导入,折线图、散点图,正态分布图分析处理导出等)

    若该文为原创文章,转载请注明原文出处本文章博客地址:https://blog.csdn.net/qq21497936/article/details/114710650长期持续带来更多项目与技术分享, ...

  4. Entity Framework发布到IIS报错

    参考资料:https://www.cnblogs.com/mrma/p/5404584.html 报错信息 The Entity Framework provider type 'System.Dat ...

  5. Redis动态配制,限内存,免重启

    p.p1 { margin: 0; font: 14px Menlo; color: rgba(0, 255, 255, 1); background-color: rgba(0, 0, 0, 0.8 ...

  6. 图数据库 NebulaGraph 的 Java 数据解析实践与指导

    如何快速.即时.符合直觉地去处理 Nebula Java Client 中的数据解析?读这一篇就够了. 图数据库 NebulaGrpah 的论坛和微信群里,有不少用户问及了 Java 客户端数据解析的 ...

  7. Nebula Graph 1.0 Release Note

    Nebula Graph 1.0 发布了.作为一款开源分布式图数据库,Nebula Graph 1.0 版本旨在提供一个安全.高可用.高性能.具有强表达能力的查询语言的图数据库. 基本功能 DDL & ...

  8. 从 Neo4j 导入 Nebula Graph 实践见 SPark 数据导入原理

    本文主要讲述如何使用数据导入工具 Nebula Graph Exchange 将数据从 Neo4j 导入到 Nebula Graph Database.在讲述如何实操数据导入之前,我们先来了解下 Ne ...

  9. 3、dubbo核心用法

    https://dubbo.apache.org/zh/docs/v2.7/user/examples/preflight-check/ 1.启动时检查 在启动时检查依赖的服务是否可用 Dubbo 缺 ...

  10. 告别os.path,拥抱pathlib

    pathlib 模块是在Python3.4版本中首次被引入到标准库中的,作为一个可选模块.从Python3.6开始,内置的 open 函数以及 os . shutil 和 os.path 模块中的各种 ...