概述
在HarmonyOS应用开发过程中,通过Image组件加载网络图片时,通常会经历四个关键阶段:组件创建、图片资源下载、图片解码和刷新。当加载的图片资源过大时,Image组件会等待图片数据下载和解码完成后才刷新显示。由于图片下载过程耗时较长,在图片完全加载之前,页面往往会显示空白区域或占位图(通常为白色或浅色背景),这种现象被称为“Image 白块”。“Image 白块”不仅影响视觉效果,还会降低用户体验,因此在开发中应尽量避免这种情况。
图1 Image白块问题效果图
为了减少图片加载时出现的白块问题,开发者可以采用预下载和缓存机制。具体来说,可以在组件创建之前,通过网络请求将图片下载并解码,然后将图片数据缓存到应用沙箱中。当Image组件加载时,首先检查应用沙箱中是否存在该图片的缓存数据。如果缓存存在,则直接从缓存中读取图片,避免重复下载;如果缓存不存在,再进行网络请求并下载图片。通过这种方式,可以有效减少加载大尺寸网络图片时的白屏或白块现象,缩短加载时间,从而提升用户体验。
图2 Image加载网络图片两种方式对比
场景案例
在使用Navigation组件时,开发者通常会在主页引入子页面组件,并通过按钮点击实现页面跳转。如果子页面需要加载较大的网络图片,且未设置占位图,则跳转后可能会出现长时间的白块现象。为了解决这一问题,可以在父页面提前下载图片并缓存到本地。当子页面加载时,直接从缓存中读取图片数据,从而减少白块显示时间,提升用户体验。
本文将以应用沙箱提前缓存举例,给出减少Image白块出现时长的一种优化方案。
优化前:使用Image组件直接加载网络地址
以下为部分示例代码:
NavDestination() { Row() { // 不推荐用法:使用Image直接加载网络图片的方式,受到图片下载与解析的耗时影响,极易出现白块。 Image("https://www.example.com/xxx.png") // 此处请填写一个具体的网络图片地址。 .objectFit(ImageFit.Auto) .width('100%') .height('100%') } .width('100%') .height('100%') .justifyContent(FlexAlign.Center) } .title(this.name)优化后:子页面PageOne中需展示一张较大的网络图片,在父组件的aboutToAppear()中提前发起网络请求,并做判断文件是否存在,已下载的不再重复请求,存储在应用沙箱中。当父页面点击按钮跳转子页面PageOne,此时触发pixMap请求读取应用沙箱中已缓存解码的网络图片并存储在LocalStorage中,通过在子页面的Image中传入被@StorageLink修饰的变量ImageData进行数据刷新,图片送显。
图3 使用预下载的方式,由开发者灵活地处理网络图片,减少白块出现时长。
以下为关键示例代码:
1.在父组件里aboutToAppear()中提前发起网络请求,当父页面点击按钮跳转子页面PageOne,此时触发pixMap请求读取应用沙箱中已缓存解码的网络图片并存储在localStorage中。非首次点击时,不再重复调用getPixMap(),避免每次点击都从沙箱里读取文件。
aboutToAppear(): void { httpRequest(); // 在父组件提前发起网络请求 } build() { Navigation(this.childNavStack) { Column() { Button('push Path to pageOne', { stateEffect: true, type: ButtonType.Capsule }) .width('80%') .height(40) .margin({ bottom: '36vp' }) .onClick(() => { if (!localStorage.get('imageData')) { // 非首次点击,不再重复调用getPixMap(),避免每次点击都从沙箱里读取文件。 this.getPixMap(); } this.childNavStack.pushPath({ name: 'pageOne' }); }) } .width('100%') .height('100%') .justifyContent(FlexAlign.End) } .backgroundColor(Color.Transparent) .title('ParentNavigation') }2.在NetRequest.ets中定义网络请求httpRequest(),通过fs.access()检查文件是否存在,当文件存在时不再重复请求,并写入沙箱中。
export async function httpRequest() { fs.access(fileUrl, fs.AccessModeType.READ).then((res) => { // 检查文件是否存在 if (!res) { // 如沙箱里不存在地址,重新请求网络图片资源 http.createHttp() .request('https://www.example.com/xxx.png', // 此处请填写一个具体的网络图片地址。 (error: BusinessError, data: http.HttpResponse) => { if (error) { // 下载失败时不执行后续逻辑 return; } // 处理网络请求返回的数据 if (http.ResponseCode.OK === data.responseCode) { const imageData: ArrayBuffer = data.result as ArrayBuffer; // 保存图片到应用沙箱 readWriteFileWithStream(imageData); } } ) } }) }3.在子组件中通过在子页面的Image中传入被@StorageLink修饰的变量ImageData进行数据刷新,图片送显。
build() { NavDestination() { Row() { Image(this.imageData) // 正例:此时Image拿到已提前加载好的网络图片,减少了白块出现时长 .objectFit(ImageFit.Auto) .width('100%') .height('100%') } .width('100%') .height('100%') .justifyContent(FlexAlign.Center) } .title(this.name) }
性能对比分析
1、trace分析
下面,使用trace对优化前后性能进行对比分析。
优化前查看trace数据,分析阶段的起点为父页面点击按钮开始计时即trace的H:DispatchTouchEvent,结束点为子页面图片渲染的首帧出现即H:CreateImagePixelMap标签后的第一个Vsync,记录白块出现时间为1.3s,其中以H:HttpRequestInner的标签起始为起点到H:DownloadImageSuccess标签结束为终点记录时间,即为网络下载耗时1.2s,因此使用Image直接加载网络图片时,出现长时间Image白块,其原因是需要等待网络下载资源完成。
图4 直接使用Image加载网络数据
优化后查看trace数据,分析阶段的起点为父页面点击按钮开始计时即trace的H:DispatchTouchEvent,结束点为子页面图片渲染的首帧出现即H:CreateImagePixelMap标签后的第一个Vsync,记录白块出现时间为32.6ms,其中记录H:HttpRequestInner的标签耗时即为提前网络下载的耗时1.16s,对比白块时长可知提前预下载可以减少白块出现时长。
图5 使用预下载的方式
说明:网络下载耗时实际受到网络波动影响,优化前后的网络下载耗时数据总体差异在1s内,提供的性能数值仅供参考。
2、效果对比
优化前直接使用Image加载网络数据,未使用预下载 | 优化后使用预下载 |
3、数据对比
对比数据如下:
方案 | 白块出现时长(毫秒) | 白块出现时长 |
---|---|---|
(优化前)直接使用Image加载网络数据,未使用预下载 | 1300 | 图片位置白块出现时间较长 |
(优化后)使用预下载 | 32.6 | 图片位置白块出现时间较短 |
说明:测试数据仅限于示例程序,不同设备特性和具体应用场景的多样性,所获得的性能数据存在差异,提供的数值仅供参考。
由此可见,加载网络图片时,使用预下载,提前处理网络请求并从应用沙箱中读取缓存数据的方式,可以减少用户可见Image白屏或白块出现时长,提升用户体验。
更详细内容请参考:https://developer.huawei.com/consumer/cn/doc/best-practices-V5/bpta-image-white-lump-solution-V5
-
Image
+关注
关注
0文章
33浏览量
12023 -
组件
+关注
关注
1文章
524浏览量
18068 -
HarmonyOS
+关注
关注
79文章
1997浏览量
31199
原文标题:HarmonyOS应用Image白块问题解决方案
文章出处:【微信号:HarmonyOS_Dev,微信公众号:HarmonyOS开发者】欢迎添加关注!文章转载请注明出处。
发布评论请先 登录
相关推荐
HarmonyOS开发案例:【image、image-animator组件】

HarmonyOS开发案例:【基础组件Slider的使用】

HarmonyOS开发--1、组件化的设计方案
HarmonyOS实战—Image组件的剪切和缩放
HarmonyOS组件更新,新增700+开源组件
讲解一下HarmonyOS中的几个自定义组件用到的知识
HarmonyOS应用开发资料(Svg组件)
【组件资料】HarmonyOS三方件开发指南
HarmonyOS/OpenHarmony应用开发-声明式开发范式组件汇总
HarmonyOS元服务-动态创建组件
HarmonyOS的组件化设计方案
鸿蒙ArkTS声明式组件:Image

评论