0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

解决HarmonyOS应用中Image组件白块问题的有效方案

HarmonyOS开发者 来源:HarmonyOS开发者 作者:HarmonyOS开发者 2025-02-17 10:08 次阅读

概述

HarmonyOS应用开发过程中,通过Image组件加载网络图片时,通常会经历四个关键阶段:组件创建、图片资源下载、图片解码和刷新。当加载的图片资源过大时,Image组件会等待图片数据下载和解码完成后才刷新显示。由于图片下载过程耗时较长,在图片完全加载之前,页面往往会显示空白区域或占位图(通常为白色或浅色背景),这种现象被称为“Image 白块”。“Image 白块”不仅影响视觉效果,还会降低用户体验,因此在开发中应尽量避免这种情况。

92506c88-eab5-11ef-9310-92fbcf53809c.gif

图1 Image白块问题效果图

为了减少图片加载时出现的白块问题,开发者可以采用预下载和缓存机制。具体来说,可以在组件创建之前,通过网络请求将图片下载并解码,然后将图片数据缓存到应用沙箱中。当Image组件加载时,首先检查应用沙箱中是否存在该图片的缓存数据。如果缓存存在,则直接从缓存中读取图片,避免重复下载;如果缓存不存在,再进行网络请求并下载图片。通过这种方式,可以有效减少加载大尺寸网络图片时的白屏或白块现象,缩短加载时间,从而提升用户体验。

9297abc0-eab5-11ef-9310-92fbcf53809c.png

图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进行数据刷新,图片送显。

92ad46ce-eab5-11ef-9310-92fbcf53809c.png

图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白块,其原因是需要等待网络下载资源完成。

92cd21ba-eab5-11ef-9310-92fbcf53809c.png

图4 直接使用Image加载网络数据

优化后查看trace数据,分析阶段的起点为父页面点击按钮开始计时即trace的H:DispatchTouchEvent,结束点为子页面图片渲染的首帧出现即H:CreateImagePixelMap标签后的第一个Vsync,记录白块出现时间为32.6ms,其中记录H:HttpRequestInner的标签耗时即为提前网络下载的耗时1.16s,对比白块时长可知提前预下载可以减少白块出现时长。

92ecdf82-eab5-11ef-9310-92fbcf53809c.png

图5 使用预下载的方式

说明:网络下载耗时实际受到网络波动影响,优化前后的网络下载耗时数据总体差异在1s内,提供的性能数值仅供参考。

2、效果对比

优化前直接使用Image加载网络数据,未使用预下载 优化后使用预下载

92506c88-eab5-11ef-9310-92fbcf53809c.gif

932ce046-eab5-11ef-9310-92fbcf53809c.gif

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开发案例:【imageimage-animator组件

    OpenHarmony提供了常用的图片、图片帧动画播放器组件,开发者可以根据实际场景和开发需求,实现不同的界面交互效果,包括:点击阴影效果、点击切换状态、点击动画效果、点击切换动效。
    的头像 发表于 04-26 17:32 1643次阅读
    <b class='flag-5'>HarmonyOS</b>开发案例:【<b class='flag-5'>image</b>、<b class='flag-5'>image</b>-animator<b class='flag-5'>组件</b>】

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

    学习如何使用声明式UI编程框架的基础组件。本篇Codelab将会使用Image组件、Slider组件、Text组件共同实现一个可调节的风车动
    的头像 发表于 05-10 16:01 815次阅读
    <b class='flag-5'>HarmonyOS</b>开发案例:【基础<b class='flag-5'>组件</b>Slider的使用】

    HarmonyOS开发案例:【常用组件与布局】

    HarmonyOS ArkUI提供了丰富多样的UI组件,您可以使用这些组件轻松地编写出更加丰富、漂亮的界面。
    的头像 发表于 05-09 18:20 1421次阅读
    <b class='flag-5'>HarmonyOS</b>开发案例:【常用<b class='flag-5'>组件</b>与布局】

    HarmonyOS开发--1、组件化的设计方案

    ”的系统能力为各种硬件开发提供了全栈的软件解决方案,并保持了上层接口的统一和分布式能力的统一。HarmonyOS通过组件化和小型化等设计方法,做到硬件资源的可大可小,在多种终端设备间,按需弹性部署
    发表于 09-14 11:30

    HarmonyOS实战—Image组件的剪切和缩放

    1. Image图片标签概述:图片(Image)是用来显示图片的组件。常见的属性:id,长、宽、高等。具体可以参考华为开发手册(组件的通用属性):https
    发表于 08-17 18:00

    HarmonyOS组件更新,新增700+开源组件

    组件是对数据和方法的简单封装,通过使用现成的组件让应用开发更加简单高效。自HarmonyOS组件开源以来,经两次上线,已开源了700+的Java/JS
    发表于 11-18 11:17

    讲解一下HarmonyOS的几个自定义组件用到的知识

    看下 DrawTask 的描述:在项目开发,我们经常会用到自定义组件,此处分享一下 HarmonyOS JS 如何利用 canvas 实现自定义
    发表于 03-16 16:05

    HarmonyOS应用开发资料(Svg组件

    1、HarmonyOS应用开发-Svg组件circle  该组件从API version 7开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。2、HarmonyOS
    发表于 03-17 14:49

    组件资料】HarmonyOS三方件开发指南

    显示。1.2.模拟器上运行效果:2、HarmonyOS三方件开发指南——AsyncHttpHarmony组件1.AsyncHttpHarmony功能介绍1.1.组件介绍在做HarmonyOS
    发表于 03-21 11:18

    求助,请问如何发布我的HarmonyOS组件或解决方案

    我要如何发布我的HarmonyOS组件或解决方案
    发表于 06-02 15:55

    HarmonyOS/OpenHarmony应用开发-声明式开发范式组件汇总

    类型基础组件Blank、Button、Checkbox、CheckboxGroup、DataPanel、DatePicker、Divider、Gauge、Image、ImageAnimator
    发表于 01-19 11:14

    HarmonyOS元服务-动态创建组件

    示例效果:提供在页面动态添加组件,并为动态添加的组件设置属性与样式的能力(API version 8开始支持)。示例代码:index.hml<div class="
    发表于 03-29 10:52

    HarmonyOS组件化设计方案

    能力、适配多种终端形态”,HarmonyOS采用了“组件化”的设计方案,实现根据设备的资源能力和业务特征灵活裁剪,满足不同形态终端设备对操作系统的要求。 一、为什么采用“组件化”设计
    的头像 发表于 10-13 09:59 2403次阅读

    OpenHarmony应用开发之ETS开发方式Image组件

    今天带大家了解ETS开发方式Image组件
    的头像 发表于 07-03 12:06 3630次阅读
    OpenHarmony应用开发之ETS开发方式<b class='flag-5'>Image</b><b class='flag-5'>组件</b>

    鸿蒙ArkTS声明式组件Image

    Image为图片组件,常用于在应用显示图片。Image支持加载[PixelMap]、[ResourceStr]和[DrawableDescriptor]类型的数据源,支持png、jp
    的头像 发表于 06-23 20:32 1320次阅读
    鸿蒙ArkTS声明式<b class='flag-5'>组件</b>:<b class='flag-5'>Image</b>