成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

RN框架在攜程旅行鴻蒙應用的全業務適配實踐

開發 移動開發
攜程作為鴻蒙生態在旅游行業的重要合作伙伴,早在鴻蒙服務卡片時期就和華為開始合作。2023年9月,華為宣布鴻蒙原生應用啟動開發,同年12月,我們完成攜程旅行鴻蒙Beta版本的開發,技術上基于Web+部分原生的方案實現。24年6月HarmonyOS Next系統正式內測后,為了讓鴻蒙生態的用戶使用到攜程一站式的旅行服務,我們開始在鴻蒙系統上對全業務進行適配。

一、RN在攜程業務使用現狀

2019年,攜程開始在線上使用RN框架,并結合自身的業場景,對RN框架進行了開發和改造,研發了CRN框架(以下簡稱CRN)。2021年,CRN成為攜程主流的開發框架。集團內有20+個App接入CRN框架,其中核心的App都已接入。攜程旅行App中,200+個業務Bundle在線上運行,業務頁面數量超過2000個,超過80%的業務使用CRN。

二、技術選型(為什么選擇CRN)

從新技術的選擇到落地的實踐上看,業務對技術的要求往往是以下幾個方面:

1)功能全,全量業務都能快速的適配上線

2)性能好,用戶體驗多端一致

3)成本低,復用現有在其他平臺的運行的代碼

為了滿足業務需求,鴻蒙的實現技術上我們選擇了CRN,主要考慮:

1)基建成熟度高:有配套研發/測試/發布/運營監控系統,內部交流活躍,知識沉淀深

2)業務適配成本小:業務不需要重新再開發一遍,可以使用現有的業務代碼

3)開發能快速上手:業務開發還是使用原有的技術進行開發,在鴻蒙上運行

4)產品迭代效率:支持每個周期的產品迭代,快速在鴻蒙系統的手機上線

三、CRN適配實踐

3.1 版本升級

線上攜程旅行App使用的React Native(RN)版本是0.70.1,而鴻蒙RN版本是0.72.5。因此,適配鴻蒙的第一步是將RN版本從0.70.1升級到0.72.5。

版本升級包含了如下幾個方面:

3.1.1 RN版本差異分析

我們對比RN 0.70.1 和 0.72.5 框架庫的差異,整體改動點不多。為了降低業務方升級成本,我們在框架底層對廢棄的組件和API變更做了兼容,盡可能減少業務使用方的改動。

3.1.2 CRN框架改造

CRN框架覆蓋了文檔、工具、開發框架、發布、監控、排障全鏈路。對應框架的改造也從這幾個方面進行。

1)在文檔方面,我們編寫了詳細的業務升級文檔,列出業務方需要關注的點和常見問題。

2)在工具方面,提供了一鍵式CLI升級工具,只需在業務工程執行一行升級命令,即可完成工程升級改造。

3)在開發框架方面,改造涉及點比較多,包括:

  • 對Native運行時升級,升級RN 0.72.5 核心庫,合并對官方RN庫的自定義改動點。
  • 對JS打包工具升級,支持現有的拆包邏輯,合并對官方RN庫的自定義改動點。
  • 梳理使用到的社區三方庫,統一三方庫版本升級至鴻蒙RN三方庫要求版本。
  • 對Hermes引擎進行升級,合并自定義改動點。
  • 對RN自定義組件和API進行新架構改造。

4)在發布方面,對現有的CRN發布系統進行改造,支持選擇鴻蒙平臺進行單獨發布。發布的產物下發和線上IOS/Android進行隔離,保證測試上線階段,不影響已經上架的IOS/Android應用。

待后續鴻蒙應用穩定,再支持一鍵同時發布IOS/Android/HarmonyOS Next平臺。

又考慮到業務場景存在一套代碼,跨RN版本發布。發布系統改造,支持了發布時根據發布單選擇的RN版本,自動選擇依賴配置進行打包發布。提升業務發布效率。

5)在監控方面,實現鴻蒙端的監控數據上報,接入到現有的監控系統,方便線上監控。

6)在排障方面,實現鴻蒙端的異常數據上報,接入現有排障系統,方便線上排障。

3.1.3 業務工程改造

1)業務方按照提供升級文檔和工具進行具體業務工程改造。

2)升級改造后,進行本地開發環境測試,發現問題,解決問題。

3)本地測試通過后,進行打包發布,進入集成測試階段。

在升級過程中,工作量最大的部分是“RN自定義組件和API實現新架構改造”。

這里先介紹下RN新架構。RN新架構是指從0.68版本開始后的架構。主要包括:

  • Turo Modules 模塊系統,替換老架構中的Native Modules,用于JS到Native的API同步調用。
  • Farbic 組件系統,替換老架構中Native Component,支持同步渲染。

由于鴻蒙RN只支持新架構,所以需要將RN自定義組件和API實現進行新架構改造。在攜程旅行App中,我們使用有100+的自定義組件和API。這部分的改造工作量非常大,建議在做適配時優先處理這部分工作。

3.2 差異化工作

在RN版本升級到0.72.5后,開始鴻蒙端特有的適配。

鴻蒙RN框架特點:

  • 已實現了官方RN大部分組件、API
  • 已實現社區常用的三方庫
  • 自定義組件和API需要應用開發自行實現

差異化工作:

1)自定義組件和API實現

  • 100+自定義組件和API,基于鴻蒙原生開發實現,再封裝提供給RN調用
  • 按優先級分階段實現這些自定義組件和API,保持上層JS接口不變

2)RN工程改造

  • 添加react-native-harmony和react-native-harmony-cli依賴庫
  • 適配Platform.OS,Platform.select等API
  • 實現xxx.harmony.js文件,邏輯與IOS保持一致
  • 升級三方庫版本,如react-native-gesture-handler,從1.X版本升級到2.X版本
  • 三方庫版本升級后,對不兼容的地方做適配

3.3 原生組件開發

攜程CRN框架經過近8年的迭代,業務線非常復雜,自定義的組件、turboModule有100多個。

在鴻蒙中適配CRN,首先面臨的工作就是將這些自定義組件、turboModule在鴻蒙原生端用ArkTS重新實現。

我們面臨以下幾個挑戰:

1)工作量

這些組件經過了近8年的迭代,開發負責人可能幾經易手。有些復雜組件,如信息流組件、自定義地圖、日歷組件、多媒體組件等,邏輯異常復雜,經過跟原開發負責人、產品等初步討論,工作量都超過單人一個半月。而我們面臨的是100多個組件、turboModule的重實現。

2)HarmonyOS Next逐步完善,與Android、iOS在某些特性上有差異

開發過程中發現了很多HarmonyOS Next功能不完善、存在若干Bug的地方,畢竟是一個新系統,我們與華為同學緊密合作,一一解決了問題,這個過程見證了鴻蒙系統的愈發成熟。

出于安全考慮,鴻蒙系統有一些新特性,比如選取圖片視頻進行編輯的場景,在Android、iOS中,申請用戶權限之后便可以拿到整個系統相冊的圖片視頻,這確實可能存在一些安全隱患。鴻蒙在最開始就切割了這一操作,即使App經用戶同意申請了讀相冊權限,也無法拿到系統主相冊的圖片視頻,本意是讓App直接跳到系統相冊選取圖片之后返回,只提供當次選中的圖片信息給App,從而徹底斷絕了App侵犯用戶隱私的可能。

但我們的多媒體場景比較復雜,用戶選取圖片、視頻后會跳入編輯頁,且可以重回相冊頁選擇其他圖片,也就是說我們的圖片視頻選擇頁與編輯頁存在聯動,鴻蒙提供的這種跳入系統相冊的方式顯示無法滿足我們的需求。

后續經過討論,鴻蒙提供了相冊Picker的方案,將系統相冊頁封裝為組件提供給開發者,我們的圖片視頻選擇頁可以內嵌相冊Picker,從而解決了聯動的問題。但這個需求從開始評審、開發、測試到最終實現,花費了幾個月的時間。

3)RN組件C化

在接入RN的過程中,發現鴻蒙中RN關鍵性能指標與Android、iOS有差距,華為鴻蒙RN團隊為了解決性能問題,提出了組件C化的方案。

簡單來講,就是將ArkTS實現的組件用C-Api重新實現一遍,華為方面給出的要求是容器結點(RN代碼中存在標簽<></>嵌套的組件)需強制C化。雖然攜程中這種必須C化的組件并不多,但也帶來了非常多的適配工作。具體可參考下篇-組件C化。

部分組件圖如下:

圖片


Fabric、TurboModule

最開始,我們在實現相關Fabric、TurboModule的時候,鴻蒙RN框架還沒有提供Spec文件CodeGen工具,全靠手寫。不過現在已經提供了相關工具,具體操作步驟可以參考相關文檔。

Spec文件生成之后,剩下的工作就是相關組件、TurboModule的功能橋接實現,邏輯較為簡單,實現相關功能就好。

需要注意的是:

  • RN代碼中存在標簽<></>嵌套的組件被視為容器結點,此類型組件需使用C-API實現。
  • 可以通過this.ctx獲取RNOHContext,進而獲取RNInstance,從而獲取一系列RN端JS傳入的信息,如View寬高、style等,也可執行發送事件、接收事件、獲取TurboModule進行其他操作等等。
  • 在RNInstanceImpl構造函數中有一個arkTsComponentNames字段,可以傳入所有我們自定義葉子結點Fabric組件的名稱,用于在RNOH SDK內部進行指令分發優化。實現ArkTS端Fabric組件后,需要將Fabric組件的名稱加入此列表中。
  • 假設存在實現過于復雜或者其他原因無法C化的容器組件,RNOH SDK內部指令優化代碼需修改(這也意味著RNOH SDK需重新打包編譯),關鍵代碼見下文‘性能優化-5.3 RN 指令精簡章節。

3.4 組件C化

經過與華為的詳細溝通,RN代碼中存在標簽<></>嵌套的組件被視為容器結點,此類型組件需強制C化。

也就是此類型的組件:

<RNComponent>

    <Text/>

    <Image/>

</RNComponent>

RNComponent算為容器結點

經確認,攜程端存在四個需強制C化的容器結點組件,分別為:

名稱

描述

SwipeoutView

可滑動組件

ScrollView

滾動組件

CustomScrollView

自定義列表組件

CRNModal

modal容器

簡而言之,需要把ArkTS端實現的組件用C-Api再次實現。

3.4.1 CRNModal C化

CRNModal 在開發測試過程中一步步探索了實現方案,經過多輪測試、方案討論調整,最終確定了C化方案。

方案一:嘗試使用系統Modal實現這個組件

后續測試過程中發現系統Modal的實現方案為系統Dialog,層級很高,攜程業務線會出現這樣一種場景,RN頁面打開Modal后點擊跳轉一個其他頁面,新打開的頁面會出現在Modal的下方,不符合需求,方案淘汰。

方案二:嘗試通過新跳轉一個透明頁面的方式實現modal

測試發現新跳轉一個頁面后,RN的點擊事件分發出現問題,無法響應任何事件。且我們App的路由方案為Navigation,經與華為方面溝通,Navigation C化難度非常巨大,短時間不可行。此方案淘汰。

方案三:嘗試在RN JS端創建modal

JS端創建一個style為position: 'absolute', zIndex: 999的容器,層級提高,顯示在其他組件上方來實現modal。測試發現調用顯示Modal的地方很多,可能會在一個嵌套很深的層級中,如果在這里嘗試展示這個zIndex: 999的容器,還是會有被遮擋的情況,最終此方案也被淘汰。

方案四:C++層進行插入

經過內部討論,這個modal應該展示在整個RN頁面層級的最上方,這在Android、iOS中都很好實現,但鴻蒙是一個聲明式的語言,無法拿到頁面實例,無法拿到父組件,也就無法進行插入。

但研究RNOH SDK之后發現,C化后的RNInstance實例在C++端持有一個XComponentSurface,所有RN頁面對應的Native組件都被添加顯示在這里,而XComponentSurface可以獲取rootView實例ComponentInstance,這是一個根控件,將這個根控件強轉為ViewComponentInstance之后,在ViewComponentInstance.cpp代碼中可以類似Android,獲取childCount,通過index添加child等等,進而可以實現在RN頁面層級最上方添加modal,最終也是依據此方案,實現了CRNModal組件。

流程如下:

圖片


3.4.2 開發注意事項

1)在CAPI instance中聲明的Node節點,必須在全局聲明,否則會導致node節點不能收到node_event等消息;

2)設置node屬性構建ArkUI_AttributeItem的時候,如果設置的值是一個ArkUI_NumberValue類型,需要指定size,這個size的計算必須除去類型的長度,如下:

ArkUI\_NumberValue value\[] = {{.i32 = alignItem}};
ArkUI\_AttributeItem item = {value, sizeof(value) / sizeof(ArkUI\_NumberValue)};

3)animateTo執行動畫,在組件析構之后還是會回調,需要控制好生命周期避免crash;

4)設置Stack背景,導致子組件布局錯誤,是因為Stack被作為同級組件從而導致子組件的postion參數異常,需要手動處理好position問題;

5)可以通過以下方式在C++層調用arkTS方法,獲取相關數據:

方案1:在ArkTS里實現一個TurboModule方法,然后通過rnInstance->getTurboModule<XXTurboModule>獲取對應的TurboModule,調用方法,獲取返回值。但此方案涉及C++與ArkTS的跨端調用,性能會差一些,優點是實現簡單。

方案2:通過ArkTSBridge,添加一個ArkTS方法的橋,然后就可以在C++里直接調用這個ArkTS方法。具體實現可以參考NapiBridget.ArkTSBridgeHandler里任意方法。此方案性能好,但實現起來稍微麻煩一點。

6)可以通過以下Api獲取設備的高寬

auto displayMetrics = ArkTSBridge::getInstance()->getDisplayMetrics();
 displayMetrics.screenPhysicalPixels.width / displayMetrics.screenPhysicalPixels.scale //直接獲取到是px單位,需要進行轉換,也可以自行修改TurboModle的初始化值:

四、遇到的問題和解決辦法

在升級適配過程中,我們遇到了一些RN新架構問題,還有一些鴻蒙RN特有的問題。

RN 新架構問題:

  • IOS Animated.timing 設置 useNativeDriver:true 后,內嵌按鈕無法點擊
  • IOS TouchableOpacity 內嵌 Aminated.View ,Aminated.View 開啟動畫變更位置后,無法點擊
  • IOS Image樣式設置 borderRadius 顯示不全
  • IOS minimumFontScale maxFontSizeMultiplier 不生效
  • Aminated.View 內嵌Modal組件,內部TouchableOpacity點擊不響應
  • FlatList、ScrollView stickyHeaderIndices 吸頂功能多次滑動后失效
  • Aminated.View 、Animated.ScrollView、layoutAnimation 動畫卡頓
  • 樣式中使用了zIndex屬性層級可能不生效,嘗試添加 position:relative屬性后生效
  • 組件需要設置默認高寬,不然布局展示可能發生截斷

由于動畫、樣式、性能影響較大,最終決定在RN 0.72.5版本(iOS/Andriod)中只使用Turbo Modules,不開啟Fabric模式,來規避掉這些問題。

但鴻蒙RN只支持新架構,新架構存在問題有些在鴻蒙端同樣存在。我們和華為伙伴緊密溝通來處理這些問題。對于無法規避問題只能業務側做兼容處理。

鴻蒙RN特有的問題:

問題:RN Modal彈窗顯示時,再打開一個H5頁面會顯示在Modal下面 

解決辦法:實現一個View層級的CRNModal替代RN Modal

問題:絕對定位中添加top:“auto”導致元素不顯示 

解決辦法:去除top:“auto”設置

問題:zIndex:-1元素不顯示 

解決辦法:在最外層的View添加collapsable={false}屬性

問題:position:absolute樣式漂移 

解決辦法:在外層的View添加collapsable={true}屬性

問題:react-native-harmony/metro.config 和現有的自定義metro配置沖突

解決辦法:提取react-native-harmony/metro.config中harmony平臺相關處理,合并到自定義metro插件中

五、性能優化

華為內部對鴻蒙系統寄予厚望,為了追求更好的用戶體驗,希望鴻蒙APP核心業務場景性能指標達成業內最佳水平。對攜程來說,大多數業務頁面都是RN,RN技術棧對性能指標非常敏感,很小的性能優化或劣化,都會大幅影響用戶體驗。

5.1 CRN預加載

默認情況下,我們會在頁面的生命周期中去加載rn_bundle,因為頁面已經進入生命周期開始展示了,加載bundle又會有一定的耗時,這種情況下,就會產生白屏現象。

攜程也存在某些頁面依賴接口數據且接口返回比較慢的情況,比如機票列表頁,在進入頁面白屏之后又會有長時間的骨架屏,用戶體驗差。

圖片

經過調研,攜程端基于系統的FrameNode能力,實現了CRN預加載方案,解決了上述問題。

5.1.1 FrameNode

圖片


鴻蒙中FrameNode是一個非常強大的能力,不光是各大廠商在用,官方ArkUI中也大量使用了FrameNode進行性能優化。

它的特點用一句話可以描述:后臺離屏渲染,前臺上樹展示。

利用這個特點,可以實現組件渲染與頁面展示的完全分離。也就是說組件的創建渲染不再依賴頁面的生命周期,這樣我們就可以做很多事情了。

但正因為FrameNode組件會在后臺真實渲染,它使用起來會有一定的風險,后臺渲染的組件可能會影響前臺行為,比如改變狀態欄顏色、彈Toast、彈Dialog等,這些都需要人為進行規避。

在RNSDK中我們對Toast、Dialog、狀態欄等行為的TurboModule調用,根據頁面狀態進行了攔截,頁面不可見時,上述這些TurboModule的調用都不會生效,而且會記錄最后一次攔截的行為及參數,在頁面變為可見時,恢復最后一次被攔截的行為。

基于FrameNode能力,實現了鴻蒙中CRN預加載的1.0和2.0方案,下文會詳細介紹這兩個方案。

另外需要注意的一點是,攜程在RN中使用FrameNode過程中,遇過一個困擾許久的問題:使用FrameNode加載RN頁面時,在某些比較復雜的頁面,會發生非常嚴重的JS阻塞現象,用戶的點擊、返回等操作行為被頁面渲染指令阻塞,遲遲得不到響應,極度影響用戶體驗。

經過與華為方面的聯合排查,發現是因為RNInstance初始化時傳入的參數:disableCnotallow=true導致。此參數會關閉React18一個性能優化的功能:微任務指令批量提交,從而導致在JS代碼setTimeout中進行setState時,指令立即提交,總指令數大幅增加,進而大幅影響RN指令處理效率。

大家如果也會在項目中用到FrameNode進行RN頁面的性能優化,在初始化RNInstance時,disableConcurrentRoot參數一定要傳false。

5.1.2 CRN分包

要理解我們CRN的預加載方案,首先要了解我們的分包邏輯,具體可參考文章:《近萬字長文詳述攜程大規模應用RN的工程化實踐》

總體而言,將業務bundle的加載分為兩部分: rn_common & rn_business。其中rn_common包含完整的基礎框架能力,rn_business則是具體的業務邏輯代碼。通過nativeRequire的方式,分行加載rn_business中的業務代碼,然后在加載了rn_common的空白頁面上進行渲染。

可以發現,CRN這種分包模式完美契合FrameNode,我們使用FrameNode預渲染一個加載了rn_common的空白頁面,這個空白頁面不會渲染UI元素且具備完整的框架能力,不會有任何影響前臺頁面的行為,等到頁面真正展示時,才去加載業務代碼rn_business,進行UI渲染,從而完美規避FrameNode的使用風險。

也正是基于此,我們實現了CRN預加載1.0的方案。

5.1.3 CRN預加載1.0

圖片


預加載1.0方案:

  • 在前置頁面通過FrameNode預加載一個RNSurface,利用這個RNSurface去加載rn_common,完成后可以理解為后臺存在了一個具備所有框架能力的空白頁面。
  • 用戶點擊跳轉RN頁面時,添加一個用戶幾乎不可感知的延時去加載rn_business。
  • 充分利用這個跳轉延時 + 頁面創建 + 頁面切換的動畫時間去加載業務bundle、渲染等。
  • 業務Bundle加載完成后,動態替換業務自定義的intialProps
  • 做到了rn bundle加載、 渲染與頁面生命周期的完全隔離。
  • 目前預加載1.0方案在全業務默認使用,基本解決了RN頁面首幀白屏問題。

在攜程的某些業務線中,頁面UI依賴網絡接口數據,且受外部接口影響,響應較慢。這時候,打開頁面會有較長時間的骨架屏loading,也非常影響用戶體驗。

如果在前置頁面中,我們可以大概率猜到用戶下一步跳入的目標頁面,那是不是可以利用FrameNode將目標頁面提前加載,且根據前置頁面的參數進行動態刷新,這樣用戶真正跳入目標頁面的時候,就可以直接上屏,達到秒開的效果。

基于此,我們實現了CRN預加載2.0。

5.1.4 CRN預加載2.0

圖片

預加載2.0方案:

  • 在前置頁面通過FrameNode預加載了一個真實的RN頁面,完成了加載rn_commom、rn_business、接口請求、渲染等一系列流程。
  • 前置頁面中影響下一個頁面關鍵參數發生改變時,發消息給后臺預加載的的RN頁面,RN頁面接收到事件,拿到關鍵參數后進行網絡請求,得到數據后對頁面進行刷新。
  • 用戶點擊跳轉到目標頁面時,直接將后臺已經預渲染好的頁面上屏展示。
  • 因為頁面已經在后臺被真實渲染,有影響前置頁面的風險,雖然我們在RN SDK層面已經做了一層攔截,但這種攔截不可能cover所有場景,所有接入了預加載2.0方案的業務都必須在上線前經過完整回歸測試。
  • 目前,我們在機票列表頁及火車票詳情頁使用了預加載2.0方案。

對比視頻:

性能優化關閉:


圖片

性能優化開啟:

圖片

5.2 RN TurboModule運行在Worker線程

前段時間我們在RN JS端對TurboModule調用加了一個埋點,統計TurboModule方法調用的耗時,后續也是根據這個埋點生成了一個報表,發現在鴻蒙中,TurboModule同步方法調用耗時比Android、iOS耗時長10倍,某些方法甚至慢100倍。

圖片


經過分析,在Android、iOS中TurboModule都是運行在單獨的子線程中,而在鴻蒙中,TurboModule都運行在主線程,主線程要承載一些別的任務比如頁面渲染、用戶操作行為響應等,這些行為會導致鴻蒙中TurboModule的調用被阻塞,耗時就長。比如下圖的Trace,如果TurboModule在UI線程運行,那就可能會被阻塞,阻塞的這段時間,js線程只能等待,而這段等待是毫無意義的。

圖片


前段時間,鴻蒙RN SDK也是加入了TurboModule運行在Worker線程這個能力。RNInstance在創建時會同步創建一個worker線程,專門用于TurboModule運行。我們要做的是對工程中TurboModule代碼進行適配改造,使之可以運行到worker線程中。

整個適配過程也存在一系列的問題。

首先,鴻蒙的ArkTS衍生自TS語言,基于Actor線程模型,內存不共享,線程間數據通信非常麻煩。

為了解決線程間通信流程繁瑣的問題,鴻蒙提供了Sendable注解,可以理解為被這個注解修飾的對象會在共享內存創建。但Sendable存在一個問題,Sendable對象的成員變量只能是Sendable對象或其他特定的數據類型,也就是說我們如果對一個對象進行Sendable改造,就必須對他的所有成員變量進行Sendable改造,也需要對成員變量的成員變量進行Sendable改造,那這個改造過程就存在指數級擴散的問題。

另外,Sendable注解提供的時候,我們大部分代碼都已經完成了,在這種成熟的大型項目中再重新進行Sendable改造的成本非常高,大家各自App如果還沒開始或者剛開始開發,一定要考慮Sendable適配的問題,比如數據類型默認使用collection下屬map、array,class默認添加Sendable注解等。

目前,我們適配完成了7個TurboModule,其他TurboModule做Sendable適配的成本非常高,正在逐步進行中。

5.3 RN 指令精簡

在鴻蒙中,RN支持兩套組件:C-API實現的組件以及原生ArkTS實現的組件。

C-API實現的組件性能更好,華為的支持力度更大,出于性能考慮,大多數廠商使用RN時,都會選擇C-API實現的組件。

C-API組件的Create、Insert、Update、Remove等指令不再需要傳遞給ArkTS側。僅僅幾個自定義的ArkTS組件需要將指令傳遞給ArkTS側。如下圖中綠色節點的指令。

圖片

鴻蒙RNOH SDK中有默認算法,可以保留葉子節點ArkTS組件的指令,如果項目內沒有ArkTS容器組件,RNInstance初始化時添加配置arkTsComponentNames就好。

但在攜程的業務中存在AdatpterMap這個容器組件,依賴系統花瓣地圖,這個地圖C化難度巨大,所以我們的AdatpterMap暫時也只能由ArkTS實現。

這就需要我們自己設計算法。在保證性能的情況下,完整保留AdatpterMap及其子組件的相關指令。

以下是關鍵代碼:

RNOHSDK/src/main/cpp/RNOH/MountingManagerCAPI.cpp::getValidMutations:

facebook::react::ShadowViewMutationList MountingManagerCAPI::getValidMutations(
  facebook::react::ShadowViewMutationList const& mutations) {


...
//需要特殊處理,保留容器組件及其子組件所有指令的容器組件名稱
std::unordered_set<std::string> whiteListArkTsComponentNames = {
    "AdapterMap", "AdapterMapMarkersContainer", "AdapterMapMarker"};
//第一次遍歷:只遍歷create,從前到后找到混合組件名稱,只保存tag
for (auto mutation : mutations) {
  if (mutation.type == facebook::react::ShadowViewMutation::Create) {
    ...
    //特殊保留地圖容器組件tag
    if (whiteListArkTsComponentNames
            .count(newChild.componentName)) {
      arkTsComponentTags.push(newChild.tag);
    }
  }
}


if (!arkTsComponentTags.empty()) {
  // 第二次遍歷:只遍歷insert,找到混合組件tag和它的子組件的tag。采用廣度遍歷方式,這里也只保存tag
  for (auto mutation : mutations) {
    if (mutation.type == facebook::react::ShadowViewMutation::Insert) {
       ...
       //保存地圖容器組件tag和它的子組件的tag
    }
  }
}


//第三次遍歷:根據2中齊全的tag,重新過濾所有指令,保留這些tag的create、insert、update、remove指令。
for (auto mutation : mutations) {
  ...
  //根據組件Tag,保留需要傳遞給ArkTS的所有指令
}
 return validMutations;
}

再來看下成果,測試RN頁面中,算法過濾的不需要傳遞到ArkTS側的指令數超過99.9%。

頁面

優化前指令數

優化后指令數

酒店首頁

3092

11

酒店套餐

2181

0

機票+酒店

496

2

酒店

3838

3

美食/購物

1542

3

5.4 分幀渲染

分幀渲染主要用在App的啟動優化中。首頁宮格存在兩屏,二屏在剛開始是不可見的,可以在首頁加載完畢之后再去加載宮格二屏。

圖片

分幀渲染可以監聽到幀渲染的回調,這樣就可以對頁面元素的加載優先級進行定制,將重要的元素優先加載,不重要或者不可見的元素后續加載。進而提升頁面的性能。

關鍵代碼:

private myDisplaySync?: displaySync.DisplaySync


updateStage() {
    if (this.stages == 0) {
      this.myDisplaySync = displaySync.create();
      this.myDisplaySync.start();
      this.myDisplaySync.on('frame', (frameInfo: displaySync.IntervalInfo) => {
        this.updateStage();
      });
    }


    this.stages++;
    if (this.stages == 3) {
      this.myDisplaySync?.stop();
    }
}
...


 build() {
    Column() {
      Scroll(this.scroller) {
        Row() {
          //默認加載宮格首屏
          if (this.stages > 0){
            this.genFirstCell(0)
          }
          //三個渲染幀之后,加載宮格二屏
          if (this.stages > 2){
            this.genFirstCell(1)
          }
        }
        ...
        }

接入分幀渲染,控制宮格二屏的渲染時機后,首頁的啟動耗時減少了20ms。

5.5 后續性能優化

華為鴻蒙RN團隊規劃有一個性能優化的feature,在這里簡單介紹下。

5.5.1 更換RN JS執行引擎:JSVM(基于V8)

JSVM相較hermers,預計可以提升20%的JS解析性能。前段時間華為提供了一個rn sdk,我們新建了一個分支驗證了一下這個JSVM,js的加載速度確實比hermes要快一些。但RN產物jsbundle的加載比hermes要慢,這意味著頁面的首屏性能會受到一定影響。這是我們非常關注的一個性能指標,問題得到解決之后,我們也會進行切換。

六、成果和未來規劃

經過4個月鴻蒙版本的開發和適配,2024年6月18日攜程在鴻蒙應用商店上架了首個全業務全場景的攜程旅行鴻蒙版應用。業務方在Android/iOS上的一套CRN代碼,只需經過簡單的適配,就能正常在鴻蒙系統上運行,甚至有些業務不需要修改,現有的代碼直接在鴻蒙系統上能完整的跑完業務流程。

未來,我們還會在以下兩個方面持續對鴻蒙CRN框架進行優化:

用戶體驗

用戶體驗和性能一直是我們關注的重點,CRN在鴻蒙系統上還有很大的優化空間。我們會持續在性能上繼續打磨和提升。

技術布局

為了追求高效率、低成本的研發模式,未來攜程業務開發會大量使用一碼多端的框架xTaro。后續xTaro會支持鴻蒙系統,真正實現讓業務的一套代碼能在多端多平臺多應用場景上全矩陣運行。

鴻蒙生態的發展是一個持續且快速的過程。隨著鴻蒙系統的不斷迭代升級和生態的逐步完善,我們會持續為用戶提供更加智能、安全、便捷的一站式的旅行應用。

責任編輯:張燕妮 來源: 攜程技術
相關推薦

2022-07-15 12:58:02

鴻蒙攜程華為

2025-06-24 09:51:47

2023-06-28 14:01:13

攜程實踐

2020-11-11 13:44:00

攜程旅行點擊量

2022-09-13 13:14:53

存儲服務

2024-07-25 11:58:35

2022-05-13 09:27:55

Widget機票業務App

2023-07-07 12:26:39

攜程開發

2022-08-20 07:46:03

Dynamo攜程數據庫

2022-07-15 09:20:17

性能優化方案

2022-08-12 08:34:32

攜程數據庫上云

2022-07-08 09:38:27

攜程酒店Flutter技術跨平臺整合

2023-02-08 16:34:05

數據庫工具

2022-06-17 10:44:49

實體鏈接系統旅游AI知識圖譜攜程

2024-07-05 15:05:00

2022-05-27 09:52:36

攜程TS運營AI

2023-08-18 10:49:14

開發攜程

2009-06-19 09:52:46

Acegi安全框架Spring框架

2022-06-03 09:21:47

Svelte前端攜程
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 欧美精品网站 | 粉嫩一区二区三区性色av | 色婷婷av久久久久久久 | 日韩一区二区不卡 | 亚洲成人免费观看 | 日韩免费av一区二区 | 日本涩涩网 | 久久久久久久久久久一区二区 | 亚洲91av| 国产在线a| 欧美日韩成人一区二区 | 男女网站免费观看 | 欧美精品在欧美一区二区少妇 | 成人精品| 日韩av啪啪网站大全免费观看 | 国产aⅴ | 国产中文在线观看 | 国产日韩久久久久69影院 | 日本在线网站 | 日韩av手机在线观看 | 国产成人高清视频 | 欧美 日韩 国产 成人 在线 | 一区二区三区精品视频 | 黄色片网站在线观看 | 中文字幕高清一区 | 在线观看第一页 | 天天av网 | 国产精品日韩欧美一区二区三区 | 九色av| 日韩亚洲视频 | 久久国内 | 精品国产一区二区三区观看不卡 | 自拍偷拍中文字幕 | 亚洲精品www.| 啪啪免费网站 | 99精品99久久久久久宅男 | 午夜影院在线观看视频 | 久久国产精品视频免费看 | 欧美电影在线观看网站 | 精品入口麻豆88视频 | 欧美在线观看一区 |