0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
电子发烧友
开通电子发烧友VIP会员 尊享10大特权
海量资料免费下载
精品直播免费看
优质内容免费畅学
课程9折专享价
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

解決HarmonyOS應(yīng)用中Image組件白塊問(wèn)題的有效方案

HarmonyOS開(kāi)發(fā)者 ? 來(lái)源:HarmonyOS開(kāi)發(fā)者 ? 作者:HarmonyOS開(kāi)發(fā)者 ? 2025-02-17 10:08 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

概述

HarmonyOS應(yīng)用開(kāi)發(fā)過(guò)程中,通過(guò)Image組件加載網(wǎng)絡(luò)圖片時(shí),通常會(huì)經(jīng)歷四個(gè)關(guān)鍵階段:組件創(chuàng)建、圖片資源下載、圖片解碼和刷新。當(dāng)加載的圖片資源過(guò)大時(shí),Image組件會(huì)等待圖片數(shù)據(jù)下載和解碼完成后才刷新顯示。由于圖片下載過(guò)程耗時(shí)較長(zhǎng),在圖片完全加載之前,頁(yè)面往往會(huì)顯示空白區(qū)域或占位圖(通常為白色或淺色背景),這種現(xiàn)象被稱為“Image 白塊”?!癐mage 白塊”不僅影響視覺(jué)效果,還會(huì)降低用戶體驗(yàn),因此在開(kāi)發(fā)中應(yīng)盡量避免這種情況。

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

圖1 Image白塊問(wèn)題效果圖

為了減少圖片加載時(shí)出現(xiàn)的白塊問(wèn)題,開(kāi)發(fā)者可以采用預(yù)下載和緩存機(jī)制。具體來(lái)說(shuō),可以在組件創(chuàng)建之前,通過(guò)網(wǎng)絡(luò)請(qǐng)求將圖片下載并解碼,然后將圖片數(shù)據(jù)緩存到應(yīng)用沙箱中。當(dāng)Image組件加載時(shí),首先檢查應(yīng)用沙箱中是否存在該圖片的緩存數(shù)據(jù)。如果緩存存在,則直接從緩存中讀取圖片,避免重復(fù)下載;如果緩存不存在,再進(jìn)行網(wǎng)絡(luò)請(qǐng)求并下載圖片。通過(guò)這種方式,可以有效減少加載大尺寸網(wǎng)絡(luò)圖片時(shí)的白屏或白塊現(xiàn)象,縮短加載時(shí)間,從而提升用戶體驗(yàn)。

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

圖2 Image加載網(wǎng)絡(luò)圖片兩種方式對(duì)比

場(chǎng)景案例

在使用Navigation組件時(shí),開(kāi)發(fā)者通常會(huì)在主頁(yè)引入子頁(yè)面組件,并通過(guò)按鈕點(diǎn)擊實(shí)現(xiàn)頁(yè)面跳轉(zhuǎn)。如果子頁(yè)面需要加載較大的網(wǎng)絡(luò)圖片,且未設(shè)置占位圖,則跳轉(zhuǎn)后可能會(huì)出現(xiàn)長(zhǎng)時(shí)間的白塊現(xiàn)象。為了解決這一問(wèn)題,可以在父頁(yè)面提前下載圖片并緩存到本地。當(dāng)子頁(yè)面加載時(shí),直接從緩存中讀取圖片數(shù)據(jù),從而減少白塊顯示時(shí)間,提升用戶體驗(yàn)。

本文將以應(yīng)用沙箱提前緩存舉例,給出減少I(mǎi)mage白塊出現(xiàn)時(shí)長(zhǎng)的一種優(yōu)化方案。

優(yōu)化前:使用Image組件直接加載網(wǎng)絡(luò)地址

以下為部分示例代碼:

NavDestination() {
  Row() {
    // 不推薦用法:使用Image直接加載網(wǎng)絡(luò)圖片的方式,受到圖片下載與解析的耗時(shí)影響,極易出現(xiàn)白塊。
    Image("https://www.example.com/xxx.png") // 此處請(qǐng)?zhí)顚?xiě)一個(gè)具體的網(wǎng)絡(luò)圖片地址。
      .objectFit(ImageFit.Auto)
      .width('100%')
      .height('100%')
  }
  .width('100%')
  .height('100%')
  .justifyContent(FlexAlign.Center)
}
.title(this.name)
優(yōu)化后:子頁(yè)面PageOne中需展示一張較大的網(wǎng)絡(luò)圖片,在父組件的aboutToAppear()中提前發(fā)起網(wǎng)絡(luò)請(qǐng)求,并做判斷文件是否存在,已下載的不再重復(fù)請(qǐng)求,存儲(chǔ)在應(yīng)用沙箱中。當(dāng)父頁(yè)面點(diǎn)擊按鈕跳轉(zhuǎn)子頁(yè)面PageOne,此時(shí)觸發(fā)pixMap請(qǐng)求讀取應(yīng)用沙箱中已緩存解碼的網(wǎng)絡(luò)圖片并存儲(chǔ)在LocalStorage中,通過(guò)在子頁(yè)面的Image中傳入被@StorageLink修飾的變量ImageData進(jìn)行數(shù)據(jù)刷新,圖片送顯。

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

圖3 使用預(yù)下載的方式,由開(kāi)發(fā)者靈活地處理網(wǎng)絡(luò)圖片,減少白塊出現(xiàn)時(shí)長(zhǎng)。

以下為關(guān)鍵示例代碼:

1.在父組件里aboutToAppear()中提前發(fā)起網(wǎng)絡(luò)請(qǐng)求,當(dāng)父頁(yè)面點(diǎn)擊按鈕跳轉(zhuǎn)子頁(yè)面PageOne,此時(shí)觸發(fā)pixMap請(qǐng)求讀取應(yīng)用沙箱中已緩存解碼的網(wǎng)絡(luò)圖片并存儲(chǔ)在localStorage中。非首次點(diǎn)擊時(shí),不再重復(fù)調(diào)用getPixMap(),避免每次點(diǎn)擊都從沙箱里讀取文件。

aboutToAppear(): void {
  httpRequest(); // 在父組件提前發(fā)起網(wǎng)絡(luò)請(qǐng)求
}


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')) { // 非首次點(diǎn)擊,不再重復(fù)調(diào)用getPixMap(),避免每次點(diǎn)擊都從沙箱里讀取文件。
            this.getPixMap();
          }
          this.childNavStack.pushPath({ name: 'pageOne' });
        })
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.End)
  }
  .backgroundColor(Color.Transparent)
  .title('ParentNavigation')
}
2.在NetRequest.ets中定義網(wǎng)絡(luò)請(qǐng)求httpRequest(),通過(guò)fs.access()檢查文件是否存在,當(dāng)文件存在時(shí)不再重復(fù)請(qǐng)求,并寫(xiě)入沙箱中。
export async function httpRequest() {
  fs.access(fileUrl, fs.AccessModeType.READ).then((res) => { // 檢查文件是否存在
    if (!res) { // 如沙箱里不存在地址,重新請(qǐng)求網(wǎng)絡(luò)圖片資源
      http.createHttp()
        .request('https://www.example.com/xxx.png', // 此處請(qǐng)?zhí)顚?xiě)一個(gè)具體的網(wǎng)絡(luò)圖片地址。
          (error: BusinessError, data: http.HttpResponse) => {
            if (error) {
              // 下載失敗時(shí)不執(zhí)行后續(xù)邏輯
              return;
            }
            // 處理網(wǎng)絡(luò)請(qǐng)求返回的數(shù)據(jù)
            if (http.ResponseCode.OK === data.responseCode) {
              const imageData: ArrayBuffer = data.result as ArrayBuffer;
              // 保存圖片到應(yīng)用沙箱
              readWriteFileWithStream(imageData);
            }
          }
        )
    }
  })
}
3.在子組件中通過(guò)在子頁(yè)面的Image中傳入被@StorageLink修飾的變量ImageData進(jìn)行數(shù)據(jù)刷新,圖片送顯。
build() {
  NavDestination() {
    Row() {
      Image(this.imageData) // 正例:此時(shí)Image拿到已提前加載好的網(wǎng)絡(luò)圖片,減少了白塊出現(xiàn)時(shí)長(zhǎng)
        .objectFit(ImageFit.Auto)
        .width('100%')
        .height('100%')
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }
  .title(this.name)
}

性能對(duì)比分析

1、trace分析

下面,使用trace對(duì)優(yōu)化前后性能進(jìn)行對(duì)比分析。

優(yōu)化前查看trace數(shù)據(jù),分析階段的起點(diǎn)為父頁(yè)面點(diǎn)擊按鈕開(kāi)始計(jì)時(shí)即trace的H:DispatchTouchEvent,結(jié)束點(diǎn)為子頁(yè)面圖片渲染的首幀出現(xiàn)即H:CreateImagePixelMap標(biāo)簽后的第一個(gè)Vsync,記錄白塊出現(xiàn)時(shí)間為1.3s,其中以H:HttpRequestInner的標(biāo)簽起始為起點(diǎn)到H:DownloadImageSuccess標(biāo)簽結(jié)束為終點(diǎn)記錄時(shí)間,即為網(wǎng)絡(luò)下載耗時(shí)1.2s,因此使用Image直接加載網(wǎng)絡(luò)圖片時(shí),出現(xiàn)長(zhǎng)時(shí)間Image白塊,其原因是需要等待網(wǎng)絡(luò)下載資源完成。

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

圖4 直接使用Image加載網(wǎng)絡(luò)數(shù)據(jù)

優(yōu)化后查看trace數(shù)據(jù),分析階段的起點(diǎn)為父頁(yè)面點(diǎn)擊按鈕開(kāi)始計(jì)時(shí)即trace的H:DispatchTouchEvent,結(jié)束點(diǎn)為子頁(yè)面圖片渲染的首幀出現(xiàn)即H:CreateImagePixelMap標(biāo)簽后的第一個(gè)Vsync,記錄白塊出現(xiàn)時(shí)間為32.6ms,其中記錄H:HttpRequestInner的標(biāo)簽耗時(shí)即為提前網(wǎng)絡(luò)下載的耗時(shí)1.16s,對(duì)比白塊時(shí)長(zhǎng)可知提前預(yù)下載可以減少白塊出現(xiàn)時(shí)長(zhǎng)。

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

圖5 使用預(yù)下載的方式

說(shuō)明:網(wǎng)絡(luò)下載耗時(shí)實(shí)際受到網(wǎng)絡(luò)波動(dòng)影響,優(yōu)化前后的網(wǎng)絡(luò)下載耗時(shí)數(shù)據(jù)總體差異在1s內(nèi),提供的性能數(shù)值僅供參考。

2、效果對(duì)比

優(yōu)化前直接使用Image加載網(wǎng)絡(luò)數(shù)據(jù),未使用預(yù)下載 優(yōu)化后使用預(yù)下載

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

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

3、數(shù)據(jù)對(duì)比

對(duì)比數(shù)據(jù)如下:

方案 白塊出現(xiàn)時(shí)長(zhǎng)(毫秒) 白塊出現(xiàn)時(shí)長(zhǎng)
(優(yōu)化前)直接使用Image加載網(wǎng)絡(luò)數(shù)據(jù),未使用預(yù)下載 1300 圖片位置白塊出現(xiàn)時(shí)間較長(zhǎng)
(優(yōu)化后)使用預(yù)下載 32.6 圖片位置白塊出現(xiàn)時(shí)間較短

說(shuō)明:測(cè)試數(shù)據(jù)僅限于示例程序,不同設(shè)備特性和具體應(yīng)用場(chǎng)景的多樣性,所獲得的性能數(shù)據(jù)存在差異,提供的數(shù)值僅供參考。

由此可見(jiàn),加載網(wǎng)絡(luò)圖片時(shí),使用預(yù)下載,提前處理網(wǎng)絡(luò)請(qǐng)求并從應(yīng)用沙箱中讀取緩存數(shù)據(jù)的方式,可以減少用戶可見(jiàn)Image白屏或白塊出現(xiàn)時(shí)長(zhǎng),提升用戶體驗(yàn)。

更詳細(xì)內(nèi)容請(qǐng)參考:https://developer.huawei.com/consumer/cn/doc/best-practices-V5/bpta-image-white-lump-solution-V5

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • Image
    +關(guān)注

    關(guān)注

    0

    文章

    33

    瀏覽量

    12157
  • 組件
    +關(guān)注

    關(guān)注

    1

    文章

    531

    瀏覽量

    18361
  • HarmonyOS
    +關(guān)注

    關(guān)注

    80

    文章

    2146

    瀏覽量

    32513

原文標(biāo)題:HarmonyOS應(yīng)用Image白塊問(wèn)題解決方案

文章出處:【微信號(hào):HarmonyOS_Dev,微信公眾號(hào):HarmonyOS開(kāi)發(fā)者】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 0人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    HarmonyOS開(kāi)發(fā)案例:【image、image-animator組件

    OpenHarmony提供了常用的圖片、圖片幀動(dòng)畫(huà)播放器組件,開(kāi)發(fā)者可以根據(jù)實(shí)際場(chǎng)景和開(kāi)發(fā)需求,實(shí)現(xiàn)不同的界面交互效果,包括:點(diǎn)擊陰影效果、點(diǎn)擊切換狀態(tài)、點(diǎn)擊動(dòng)畫(huà)效果、點(diǎn)擊切換動(dòng)效。
    的頭像 發(fā)表于 04-26 17:32 ?1891次閱讀
    <b class='flag-5'>HarmonyOS</b>開(kāi)發(fā)案例:【<b class='flag-5'>image</b>、<b class='flag-5'>image</b>-animator<b class='flag-5'>組件</b>】

    HarmonyOS開(kāi)發(fā)案例:【基礎(chǔ)組件Slider的使用】

    學(xué)習(xí)如何使用聲明式UI編程框架的基礎(chǔ)組件。本篇Codelab將會(huì)使用Image組件、Slider組件、Text組件共同實(shí)現(xiàn)一個(gè)可調(diào)節(jié)的風(fēng)車(chē)動(dòng)
    的頭像 發(fā)表于 05-10 16:01 ?1025次閱讀
    <b class='flag-5'>HarmonyOS</b>開(kāi)發(fā)案例:【基礎(chǔ)<b class='flag-5'>組件</b>Slider的使用】

    HarmonyOS開(kāi)發(fā)案例:【常用組件與布局】

    HarmonyOS ArkUI提供了豐富多樣的UI組件,您可以使用這些組件輕松地編寫(xiě)出更加豐富、漂亮的界面。
    的頭像 發(fā)表于 05-09 18:20 ?1730次閱讀
    <b class='flag-5'>HarmonyOS</b>開(kāi)發(fā)案例:【常用<b class='flag-5'>組件</b>與布局】

    HarmonyOS開(kāi)發(fā)--1、組件化的設(shè)計(jì)方案

    ”的系統(tǒng)能力為各種硬件開(kāi)發(fā)提供了全棧的軟件解決方案,并保持了上層接口的統(tǒng)一和分布式能力的統(tǒng)一。HarmonyOS通過(guò)組件化和小型化等設(shè)計(jì)方法,做到硬件資源的可大可小,在多種終端設(shè)備間,按需彈性部署
    發(fā)表于 09-14 11:30

    HarmonyOS實(shí)戰(zhàn)—Image組件的剪切和縮放

    1. Image圖片標(biāo)簽概述:圖片(Image)是用來(lái)顯示圖片的組件。常見(jiàn)的屬性:id,長(zhǎng)、寬、高等。具體可以參考華為開(kāi)發(fā)手冊(cè)(組件的通用屬性):https
    發(fā)表于 08-17 18:00

    HarmonyOS組件更新,新增700+開(kāi)源組件

    組件是對(duì)數(shù)據(jù)和方法的簡(jiǎn)單封裝,通過(guò)使用現(xiàn)成的組件讓?xiě)?yīng)用開(kāi)發(fā)更加簡(jiǎn)單高效。自HarmonyOS組件開(kāi)源以來(lái),經(jīng)兩次上線,已開(kāi)源了700+的Java/JS
    發(fā)表于 11-18 11:17

    講解一下HarmonyOS的幾個(gè)自定義組件用到的知識(shí)

    看下 DrawTask 的描述:在項(xiàng)目開(kāi)發(fā),我們經(jīng)常會(huì)用到自定義組件,此處分享一下 HarmonyOS JS 如何利用 canvas 實(shí)現(xiàn)自定義
    發(fā)表于 03-16 16:05

    HarmonyOS應(yīng)用開(kāi)發(fā)資料(Svg組件

    1、HarmonyOS應(yīng)用開(kāi)發(fā)-Svg組件circle  該組件從API version 7開(kāi)始支持。后續(xù)版本如有新增內(nèi)容,則采用上角標(biāo)單獨(dú)標(biāo)記該內(nèi)容的起始版本。2、HarmonyOS
    發(fā)表于 03-17 14:49

    組件資料】HarmonyOS三方件開(kāi)發(fā)指南

    顯示。1.2.模擬器上運(yùn)行效果:2、HarmonyOS三方件開(kāi)發(fā)指南——AsyncHttpHarmony組件1.AsyncHttpHarmony功能介紹1.1.組件介紹在做HarmonyOS
    發(fā)表于 03-21 11:18

    求助,請(qǐng)問(wèn)如何發(fā)布我的HarmonyOS組件或解決方案?

    我要如何發(fā)布我的HarmonyOS組件或解決方案
    發(fā)表于 06-02 15:55

    HarmonyOS/OpenHarmony應(yīng)用開(kāi)發(fā)-聲明式開(kāi)發(fā)范式組件匯總

    類型基礎(chǔ)組件Blank、Button、Checkbox、CheckboxGroup、DataPanel、DatePicker、Divider、Gauge、Image、ImageAnimator
    發(fā)表于 01-19 11:14

    HarmonyOS元服務(wù)-動(dòng)態(tài)創(chuàng)建組件

    示例效果:提供在頁(yè)面動(dòng)態(tài)添加組件,并為動(dòng)態(tài)添加的組件設(shè)置屬性與樣式的能力(API version 8開(kāi)始支持)。示例代碼:index.hml<div class="
    發(fā)表于 03-29 10:52

    HarmonyOS組件化設(shè)計(jì)方案

    能力、適配多種終端形態(tài)”,HarmonyOS采用了“組件化”的設(shè)計(jì)方案,實(shí)現(xiàn)根據(jù)設(shè)備的資源能力和業(yè)務(wù)特征靈活裁剪,滿足不同形態(tài)終端設(shè)備對(duì)操作系統(tǒng)的要求。 一、為什么采用“組件化”設(shè)計(jì)
    的頭像 發(fā)表于 10-13 09:59 ?2720次閱讀

    OpenHarmony應(yīng)用開(kāi)發(fā)之ETS開(kāi)發(fā)方式Image組件

    今天帶大家了解ETS開(kāi)發(fā)方式Image組件
    的頭像 發(fā)表于 07-03 12:06 ?3868次閱讀
    OpenHarmony應(yīng)用開(kāi)發(fā)之ETS開(kāi)發(fā)方式<b class='flag-5'>Image</b><b class='flag-5'>組件</b>

    鴻蒙ArkTS聲明式組件Image

    Image為圖片組件,常用于在應(yīng)用顯示圖片。Image支持加載[PixelMap]、[ResourceStr]和[DrawableDescriptor]類型的數(shù)據(jù)源,支持png、jp
    的頭像 發(fā)表于 06-23 20:32 ?1841次閱讀
    鴻蒙ArkTS聲明式<b class='flag-5'>組件</b>:<b class='flag-5'>Image</b>