在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

鴻蒙跨端實踐-長列表解決方案和性能優化

京東云 ? 來源:jf_75140285 ? 作者:jf_75140285 ? 2024-09-23 15:26 ? 次閱讀

這是我參加創作者計劃的第一篇文章。

前言

長列表是前端和客戶端應用中最常見的業務場景,比如商品瀑布流等,有成千上萬條數據,因此長列表的渲染性能在iOSAndroid,Harmony,Web等各大平臺都非常重要。HarmonyOS和iOS類似也提供了自己的解決方案。Roma(羅碼)作為跨端平臺,在此基礎上進行了具體的實踐。在實踐過程中,遇到了各種問題和挑戰,經歷了ArkTS+C++架構向純C++架構的轉變,本文將圍繞實踐中的各種問題和挑戰,探討Roma的具體解決方案和優化思路。

一、鴻蒙長列表解決方案及原理

鴻蒙系統為List,WaterFlow,Grid等容器組件的數據加載和渲染提供了一次性加載方案(ForEach)和按需加載方案(LazyForEach)兩種方式。

1. 一次性加載方案(ForEach)

?ForEach:一次性加載全量數據并循環渲染。原理如下:

wKgZombxGB6ABSp1AAFjOcKituY611.png

(圖片來自鴻蒙官網)

缺點:

1) 因為要一次性加載所有的列表數據,創建所有組件節點并完成組件樹的構建,在數據量大時會非常耗時,從而導致頁面加載渲染時間過長

2) 屏幕可視區外的組件雖然不會顯示在屏幕上,但是仍然會占用內存。在系統處于高負載的情況下,更容易出現性能問題,極限情況下甚至會導致應用異常退出。

實際業務中數據條數非常多,該方案存在很嚴重的性能問題。為了解決這個性能問題,HarmonyOS提供了性能更好的解決方案

2. 按需加載方案(LazyForEach)

?LazyForEach: 實現延遲加載數據并按需渲染。原理如下:

1) 根據屏幕可視區能夠容納顯示的組件數量按需加載數據。

2) 根據加載的數據量創建組件,掛載在組件樹上,屏幕可以展示多少列表項組件,就按需創建多少個ListItem組件節點掛載在List組件樹根節點上。

3) 當組件滑出可視區域外時,框架會進行組件銷毀以降低內存占用;當組件滑入可視區域時,需要從頭完成數據加載、組件創建、掛載組件樹這一過程,直至渲染到屏幕上。

wKgaombxGCGAH0QmAAFAgYb_Lqw228.png

(圖片來自鴻蒙官網)

LazyForEach實現了按需加載,針對列表數據量大、列表組件復雜的場景,減少了頁面首次啟動時一次性加載數據的時間消耗,減少了內存峰值。可以顯著提升頁面的能效比和用戶體驗。提升性能,HarmonyOS又給出了兩種優化手段:緩存列表項(CacheCount)+組件復用(@Reusable)。

2.1 緩存列表項CacheCount

如果只有懶加載,滑動速度過快時,則會導致數據來不及加載而出現“白塊現象”。為了解決這一問題,LazyForEach懶加載可以通過設置cachedCount屬性來指定緩存數量。在設置cachedCount后,除屏幕內顯示的ListItem組件外,還會預先將屏幕可視區外指定數量的列表項數據緩存起來。這樣當緩存列表項需要從屏幕可視區外進入可視區內時,只用創建、渲染組件即可,相比不設置cachedCount提升了顯示效率。(cacheCount具體設置多少,這里依然不詳細展開,詳見后續文章。)

原理如下:

wKgZombxGCKAQ270AAE0xU-FYYU215.png

(圖片來自鴻蒙官網)

2.2 組件復用@Reusable

由上文可知LazyForEach+cacheCount方案中,當組件滑出可視區域外時,框架會進行組件銷毀以降低內存占用;當組件滑入可視區域時,需要從頭完成組件創建、掛載組件樹這一過程,直至渲染到屏幕上。而且列表頁面很多列表項的UI樣式完全相同,只有數據上的差異,如果能組件復用,就能節省組件創建的時間,因此就可以進一步提高列表頁面的加載速度和響應速度。

框架為我們提供了組件復用的能力,機制如下:

1)標記為@Reusable的組件從組件樹上被移除時,組件和其對應的JSView對象都會被放入復用緩存中,復用緩存可以通過reuseId標記為不同的緩存池。

2)當列表滑動新的ListItem將要被顯示,List組件樹上需要新建節點時,將會從相應的復用緩存池中查找可復用的組件節點。

3)找到可復用節點并對其進行更新后添加到組件樹中。從而節省了組件節點和JSView對象的創建時間。

wKgaombxGCOAUUnKAAFe0mqXki4701.png

(圖片來自鴻蒙官網)


二、動態化的長列表解決方案

結合上文HarmonyOS提供的解決方案,開始考慮動態化的長列表方案。通過前面鴻蒙跨端方案介紹文章,我們知道,跨平臺框架的核心原理是通過JavaScript在JS引擎上執行時,對虛擬DOM進行操作,通過橋接或JSI與原生端進行通信,同時通過組件抽象,這些組件在不同平臺上映射到相應的原生組件。運行時我們會有相應的節點樹:JS虛擬DOM節點樹->原生端組件節點樹->原生端渲染節點樹。長列表的渲染同樣會涉及這三棵樹,并且過程比較復雜。

1. 移植iOS、Android方案到鴻蒙

1.1 其他兩端的方案原理

?緩存池大小設置為最大N頁,每個方向N/2頁(這里的N和摩擦系數等因素有關,這里暫時不詳細展開,后面有機會專門寫文章分享)

?當組件滑出緩存區域外時,操作虛擬DOM樹刪除列表項節點,同時通過bridge在原生端進行相應列表項組件的銷毀以降低內存占用;當組件滑入緩存區域時,操作虛擬DOM樹添加列表項節點,同時通過bridge在原生端進行相應列表項組件的添加,這里從虛擬DOM節點到原生端的組件,都需要從頭完成組件創建、掛載組件樹這一過程,直至渲染到屏幕上。

?原生端列表的reuseId是一個不會重復的唯一值

wKgZombxGCiAe0D7AA_8pu0GXX8174.png

該方案已經被京東金融業務100+頁面使用,在復雜的列表頁面性能表現也非常好。優點也是顯而易見,由于跨端的核心原理決定了我們必須操作VDOM節點樹和組件樹,過程中涉及JS線程和UI線程的頻繁通信,最終行為是否一致,是否能達到我們想要的結果,這個過程涉及的細節非常多,因此一個簡單的邏輯是保證正確性的比較好的手段。這當然也得益于iOS和Android系統本身性能的優越。從上文可知我們其實無論在VDOM節點樹中,還是原生端組件樹中,新的VDOM節點/列表項組件創建或刪除的時候,都沒有復用節點或者利用系統本身的組件復用的能力,只有新創建和真刪除,這種邏輯就非常簡單明了,不容易產生bug。但是從頭創建的過程會依賴系統本身的性能。

1.2 移植后存在的問題

然而,當我們把同樣的方案移植到HarmonyOS上之后,使用ArkUI框架開發,發現肉眼可見的卡頓,抖動等掉幀現象非常嚴重,因此我們開始排查原因。并與iOS和Android系統進行對比分析,經過分析我們發現主要存在以下3個問題:

?UI層級過多。在ArkUI框架實現下,自定義組件本身必須增加一個包裹的容器,比如一個類似RomaDiv這樣的業務里最常使用的,數量最多的自定義容器組件,里面必須有個類似Stack/Flex這樣的容器組件才合法,因此這個組件本身就已經是兩層了,比其他系統就多了一層。另外有些容器組件還有系統本身生成的類似__common__ 這種層級,也會導致層級變多。層級過多,每次創建,渲染過程中的計算就更多,耗時自然就更長。

?跨語言通信鏈路長。原生組件的UI是基于ArkUI實現的,運行在方舟虛擬機中。JS代碼運行在系統的JSVM中,在C++端,兩種語言通過系統提供的NAPI通信,其中涉及各種數據類型轉換,成本自然比其他系統要高。尤其在UI層級多的情況下,成本就更高了。

?系統二次布局的問題。動態化系統架構中有三個核心線程:UI主線程,JS線程和布局計算的線程。布局方案采用的是yoga布局,可以高效地進行組件的大小,位置的計算。但是系統在此布局之后還會重新進行布局一次,這個開銷就完全沒有必要,但是卻增加了耗時,影響了性能。

針對這幾個問題,經過和華為專家溝通以后,建議我們直接使用C-API開發,但是經過深入開發和溝通之后,發現C-API目前尚有功能欠缺,而且文檔不完善,不能滿足我們當下的所有需求,因此我們決定支持ArkTS版本和C-API版本兩個版本,Q3先上線ArkTS版本,同時開發完CAPI版本,待華為進一步完善C-API后,Q4上線。


2. ArkTS版本解決方案

在已經存在以上問題的前提下,我們需要盡可能的提高列表性能,創建慢的問題,首先考慮到的就是reuse的思路。

2.1 ArkTS方案原理

?原生端UI完全依賴系統提供的懶加載LazyForEach+緩存列表項CacheCount+組件復用@Reusable,其中復用的reuseId設置為具體緩存池的類別。

?虛擬DOM節點的創建,復用,回收和銷毀的時機完全與原生端UI相對應的時機同步。由于ArkUI是聲明式語法,因此整個過程是先由原生端觸發UI占位,然后在對應的生命周期上相應的操作VDOM,再通過JSI&NAPI與原生端通信,更新原生端組件。


wKgaombxGCqAbym-AAmey3Jvn3U853.png


這個方案是真正做到了reuse/recycle的長列表,做到了比較絲滑的體驗。但是由于有了recycle/reuse的過程,也增加了更多的復雜性,有很多細節需要處理。

2.2 重點優化點

1)更新數據后UI“閃”的問題 - 不要改變鍵值key + @ObjectLink + @Observed

這個問題的根本原因是lazyForEach的迭代器key generator的鍵值key發生了變化。如果鍵值key發生了變化,框架會將這個變化的組件整體先回收,然后再重新創建。經歷這一個過程就會出現“閃”的問題。

而且,改變鍵值key去刷新UI的方式代價很大,同一類別的列表項的結構非常類似,只是顯示的文本和圖片等不一樣,不變化的組件不需要重新創建,只需要更新變化的部分即可。這種情況框架提供了裝飾器@Observed和@ObjectLink,可以監聽變化的部進行局部更新。同時,復雜列表情況下,數據源大多都是多層嵌套的對象結構,建議使用@ObjectLink而不要用@Prop,因為@Prop會進行深拷貝,會增加創建時間及內存的消耗,開銷較大,而@ObjectLink指向數據源的指針,雙向同步數據,因此這種情況下性能更優。

2)刷新/更新數據后,數據先展示其他的數據然后快速再刷成最終結果

?不要更新(可見+cacheCount)范圍內的組件的鍵值key,此范圍外的部分改變鍵值key

?手動調用列表組件的方法只更新(可見+cacheCount)范圍內的組件和對應的VDOM節點

首先產生這個問題的原因還是由于key發生了變化,每次重新創建的時候,如果當前類型的緩存池有數據,就從緩存池取出復用,然后再更新變化的部分。這個從緩存池取出的組件仍然帶有原來的數據信息,因此我們會看到先展示其他數據然后再被刷成最終結果。為了避免這個現象,首先還是不要改變key。在UI上就是已經渲染了的那些組件,也即可視加上cacheCount范圍內的組件。同時對此范圍內的組件手動調用組件的更新方法,更新組件,這時JS引擎會對這個節點進行diff,把變化的部分通過JSI與原生端通信,原生端完成最終UI的更新。范圍外的部分就按需更新key和數據源。


3)有些列表滑動過程中仍有卡頓現象

?沒有正確使用組件復用 - 使用了組件復用,實際上是無效的復用,reuseId設置一定要正確,且必須為字符串類型

復用類型 描述 復用思路
標準型 復用組件之間布局完全相同 標準復用
有限變化型 復用組件之間有不同,但是類型有限 使用reuseId或者獨立成兩個自定義組件
組合型 復用組件之間有不同,情況非常多,但是擁有共同的子組件 將復用組件改為Builder,讓內部子組件相互之間復用
全局型 組件可在不同的父組件中復用,并且不適合使用@Builder 使用BuilderNode自定義復用組件池,在整個應用中自由流轉
嵌套型 復用組件的子組件的子組件存在差異 采用化歸思想將嵌套問題轉化為上面四種標準類型來解決
無法復用型 組件之間差別很大,規律性不強,子組件也不相同 不建議使用組件復用

wKgaombxGC2AdNdAAAGiKs3Fud8318.png

標準型

wKgZombxGC6ATCBBAAGGt9OFEqs739.png

有限變化型

wKgaombxGC-Af3S7AANF-M99znw689.png

組合型

wKgZombxGDGAb9g5AANoaNcqR7Q094.png

全局型

wKgZombxGDKAe2RvAALAO1NMTPY928.png

嵌套型

此外,如果使用if/else條件語句來控制布局的結構,會導致在不同邏輯創建不同布局結構嵌套的組件,此時我們應該使用reuseId將if/else條件語句拆分為不同結構的組件

?優先使用@Builder替代自定義組件@Component,減少嵌套層級

ArkUI中使用自定義組件時,在build階段將在在后端FrameNode樹創建一個相應的CustomNode節點,在渲染階段時也會創建對應的RenderNode節點。會造成組件復用下,CustomNode創建和和RenderNod渲染的耗時,因此應該優先使用@Builder。同時減少一個自定義組件,也就是減少一次aboutToReuse的回調,也會節省耗時。

?避免不必要的狀態變量刷新,使用AttributeUpdater更新組件屬性

?避免對@Link/@ObjectLink/@Prop等自動更新的狀態變量,在aboutToReuse方法中再進行更新

?避免使用函數/方法作為復用組件創建時的入參

?避免在列表滑動過程中做大量計算或者耗時長的操作

?可以結合列表預加載,布局優化等其他常規手段進一步優化體驗

3. C-API版本解決方案

上文中我們已經提到CAPI的方案能解決UI層級過多,跨語言通信鏈路長兩個核心問題,同時也減少了狀態變量維護相應的耗時,是我們最終的解決方案。C++端我們還是采用了recycle/reuse的方案,C-API實現上我們需要自己實現類似lazyForEach的能力。

3.1 C-API方案原理

?系統提供了一個ArkUI_NodeAdapter對象來管理容器的子組件,這個對象類似事件的機制,通過相關事件通知按需生成組件。

wKgZombxGDOAcXEdAAH4PwqnZ3A821.png

(圖片來自鴻蒙官網)


?在監聽事件的回調中處理創建,回收,復用,刪除等邏輯。

wKgaombxGDaAZ7ttAA66TlWHy7E258.png


3.2 部分核心代碼

有興趣的同學可以私下聯系我。

4. 性能對比分析

使用JR APP購物車頁面(頁面結構較復雜),400條數據,分別用三種方案以及優化后測試,測試結果如下:

方案 ArkTS Create ArkTS Reuse C++ Reuse
完全顯示所用時間 1s 804ms 1s 321ms 977ms
丟幀率 12.1% 0.0% 0.0%
獨占內存 45.1M 42.3M 40.2M

測試結果表明,lazyForEach,組件復用,cacheCount,預加載等等這些方法的確提高了性能,尤其是滑動過程中出現的明顯卡頓現象,同時減少UI層級,不跨語言通信能進一步提高性能,帶來更好的體驗。


三、總結

本文通過圖文的方式介紹了HarmonyOS的長列表ArkTS解決方案以及原理,同時結合實際的實現過程介紹了ROMA動態化長列表的ArkTS和C++解決方案,相應的重點優化細節以及部分核心源碼,最后對兩者進行了性能對比分析。

如果大家覺得有幫助,千萬別忘了點贊+收藏,方便以后隨時閱讀!

動態化是一個涉及JavaScript、C++、iOS、Android、Java、Harmony、Vue、Node、Webpack、Shell等眾多領域的綜合解決方案,我們有各個領域優秀的小伙伴共同前行,大家如果想深入了解某個領域的具體實現或者提出寶貴意見,可以在評論中給我留言,隨時交流~!

審核編輯 黃宇

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • JS
    JS
    +關注

    關注

    0

    文章

    78

    瀏覽量

    18406
  • 鴻蒙系統
    +關注

    關注

    183

    文章

    2641

    瀏覽量

    67768
  • 鴻蒙
    +關注

    關注

    59

    文章

    2535

    瀏覽量

    43808
  • HarmonyOS
    +關注

    關注

    80

    文章

    2084

    瀏覽量

    32233
收藏 人收藏

    評論

    相關推薦
    熱點推薦

    鴻蒙5開發寶藏案例分享---Grid性能優化案例

    ;懶加載! ?個人心得 鴻蒙的文檔里其實埋了不少“性能寶藏”,這個案例就是典型——****用計算代替遍歷的思路,在拖拽列表、瀑布流等場景都能復用。開發時多留意社區案例,能少踩很多坑! 如果你有其他Grid的
    發表于 06-12 17:47

    鴻蒙5開發寶藏案例分享---長列表性能優化解析

    鴻蒙長列表性能優化大揭秘!告別卡頓,實戰代碼解析來了! 大家好呀~今天在翻鴻蒙開發者文檔時,發現了個
    發表于 06-12 17:40

    鴻蒙5開發寶藏案例分享---應用性能優化指南

    鴻蒙性能優化實戰指南:讓你的應用飛起來 ? 大家好!今天咱們聊聊鴻蒙(HarmonyOS)應用性能優化
    發表于 06-12 17:17

    鴻蒙5開發寶藏案例分享---線程性能優化指南

    ;>Worker</span>做多線程開發時,總遇到對象線程卡頓的問題,原來鴻蒙早就提供了解決方案。下面結合代碼和實戰案例,帶你徹底玩轉性能
    發表于 06-12 17:13

    鴻蒙5開發寶藏案例分享---Web加載時延優化解析

    ;lt;/span>) ?** 結語** 這次整理讓我深刻感受到:鴻蒙的文檔體系里藏著太多 實戰干貨 ,尤其是性能優化部分,簡直是把企業級方案直接開源了!建議大家多去「最佳
    發表于 06-12 17:11

    鴻蒙5開發寶藏案例分享---性能分析簡介

    時間 } ?** 三、這些案例能解決什么?** 問題場景 案例路徑 亮點技術 列表滾動卡頓 性能優化 > 長列表加載 分幀渲染+組件復用池
    發表于 06-12 16:58

    鴻蒙5開發寶藏案例分享---性能體驗設計

    以下是一篇基于HarmonyOS性能體驗設計文檔的開發者實踐指南,結合官方案例和代碼實現,用更親切的語言分享實用技巧: ?** 鴻蒙性能
    發表于 06-12 16:45

    鴻蒙5開發寶藏案例分享---性能優化案例解析

    玩轉這些神器,附上 代碼級解決方案 ,讓你的應用流暢到飛起~ ??一、鴻蒙性能工具全家桶 1. 開發階段:靜態代碼掃描 (Code Linter) 作用 :在編碼時實時檢測性能隱患,比
    發表于 06-12 16:36

    Kuikly鴻蒙版正式開源 —— 揭秘卓越性能適配之旅

    、系統化工作,同時為了達到高性能、原生渲染、動態化等適配目標,進行了持續的探索和優化。其核心適配工作包括:對接鴻蒙UI系統,封裝原子組件,對接事件系統,優化和解決
    發表于 06-04 16:46

    快手上線鴻蒙應用高性能解決方案:數據反序列化性能提升90%

    近日,快手在Gitee平臺上線了鴻蒙應用性能優化解決方案“QuickTransformer”,該方案針對鴻蒙應用開發中廣泛使用的三方庫“cl
    發表于 05-15 10:01

    快手上線鴻蒙應用高性能解決方案

    近日,快手在Gitee平臺上線了鴻蒙應用性能優化解決方案“QuickTransformer”,該方案針對鴻蒙應用開發中廣泛使用的三方庫“cl
    的頭像 發表于 05-14 09:11 ?370次閱讀
    快手上線<b class='flag-5'>鴻蒙</b>應用高<b class='flag-5'>性能解決方案</b>

    鴻蒙原生頁面高性能解決方案上線OpenHarmony社區 助力打造高性能原生應用

    隨著HarmonyOS NEXT的正式推出,鴻蒙原生應用開發熱度高漲,數量激增。但在三方應用鴻蒙化進程中,性能問題頻出。為此,HarmonyOS NEXT推出了一整套原生頁面高性能解決方案
    發表于 01-02 18:00

    揭秘動態化框架在鴻蒙系統下的高性能解決方案

    平臺解決方案。 在研發團隊使用后可大幅降低研發人力成本;為業務提供實時觸達、A/B觸達等能力以提升業務投放效率;同時保障了C用戶優秀的用戶體驗。 一、動態化框架原理介紹 ? ?
    的頭像 發表于 10-08 13:46 ?1354次閱讀
    揭秘動態化<b class='flag-5'>跨</b><b class='flag-5'>端</b>框架在<b class='flag-5'>鴻蒙</b>系統下的高<b class='flag-5'>性能解決方案</b>

    鴻蒙實踐-JS虛擬機架構實現

    在Roma方案中,JS虛擬機是框架的核心,負責執行動態化的JS代碼。在Android平臺采用了基于V8的J2V8,iOS平臺則使用了系統自帶的JSCore,而在HarmonyOS中,由于業界無
    的頭像 發表于 09-30 14:42 ?2901次閱讀
    <b class='flag-5'>鴻蒙</b><b class='flag-5'>跨</b><b class='flag-5'>端</b><b class='flag-5'>實踐</b>-JS虛擬機架構實現

    鴻蒙實踐-布局方案介紹

    封裝到標簽中實現,業務只需要針對標簽簡單地設置相關屬性,即可實現列表類布局,大幅提升研發效率。同時動態化也支持絕對布局以及控制視圖的顯示和隱藏等功能,使之能勝任絕大多數業務布局場景。 在京東金融App使用動態化方案適配鴻蒙系統的
    的頭像 發表于 09-18 10:26 ?1316次閱讀
    <b class='flag-5'>鴻蒙</b><b class='flag-5'>跨</b><b class='flag-5'>端</b><b class='flag-5'>實踐</b>-布局<b class='flag-5'>方案</b>介紹
    主站蜘蛛池模板: 国产成人三级视频在线观看播放 | 天天干天天爱天天操 | 91免费网站在线看入口黄 | 女的扒开尿口让男人桶 | 一级片免费看 | 日本免费一区二区三区视频 | 222网站高清免费观看 | 男人cao女人视频在线观看 | 成人国产一区二区三区 | 午夜日| 亚色在线观看 | 8050午夜| 色综合综合色综合色综合 | 一级a毛片免费观看 | 99久久99久久精品国产 | 国产精品伦子一区二区三区 | 台湾一级毛片 | 国产午夜在线观看视频播放 | 成人欧美一区二区三区视频 | 搜索黄色毛片 | 好男人社区在线观看www | 成人国产日本亚洲精品 | 在线视免费频观看韩国aaa | 精品国产自在现线看久久 | 男女吃奶一进一出动态图 | 日本免费网站 | 国产成人综合亚洲怡春院 | 美女视频黄.免费网址 | 国产一级特黄生活片 | 午夜精品久久久久久久99 | 女人张开腿让男人桶免费网站 | 伊人不卡久久大香线蕉综合影院 | 日韩综合nv一区二区在线观看 | 国产亚洲精品美女久久久 | 手机看片福利久久 | 国产好深好硬好爽我还要视频 | 成人久久伊人精品伊人 | 欧美ab在线| 国产精品好好热在线观看 | 日本成人福利视频 | 国产黄色小视频在线观看 |