概述
在HarmonyOS應用開發過程中,通過Image組件加載網絡圖片時,通常會經歷四個關鍵階段:組件創建、圖片資源下載、圖片解碼和刷新。當加載的圖片資源過大時,Image組件會等待圖片數據下載和解碼完成后才刷新顯示。由于圖片下載過程耗時較長,在圖片完全加載之前,頁面往往會顯示空白區域或占位圖(通常為白色或淺色背景),這種現象被稱為“Image 白塊”?!癐mage 白塊”不僅影響視覺效果,還會降低用戶體驗,因此在開發中應盡量避免這種情況。
圖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瀏覽量
11960 -
組件
+關注
關注
1文章
521瀏覽量
17976 -
HarmonyOS
+關注
關注
79文章
1985瀏覽量
30774
原文標題: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

評論