<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          案例:React Native在字節(jié)跳動(dòng)游戲營銷場(chǎng)景中的實(shí)踐

          共 9482字,需瀏覽 19分鐘

           ·

          2021-09-01 03:00

          ????關(guān)注后回復(fù) “進(jìn)群” ,拉你進(jìn)程序員交流群????


          作者丨熊文源

          來源丨前端之巔(ID:frontshow)

          https://mp.weixin.qq.com/s/KYt33q2H8IIRJLaa8Q8f6w

          客戶端跨端框架已經(jīng)發(fā)展了很多年了,最近比較流行的小程序、Flutter、ReactNative,都算是比較成功、成熟的框架,面向的開發(fā)者也不一樣,很多大型 App 都廣泛的使用了,筆者有幸很早就參與學(xué)習(xí)使用了這些優(yōu)秀的跨端方案,在這幾年的開發(fā)和架構(gòu)設(shè)計(jì)中,除了在 App 中支撐了千萬級(jí) DAU,也慢慢將 ReactNative 跨端方案運(yùn)用到了游戲,來提升開發(fā)、迭代效率。

          為什么選擇 React Native?

          ReactNative 是目前比較流行的跨端方案,目前支持 Android、iOS、Windows 等平臺(tái),能解決了開發(fā)中的人力和雙端統(tǒng)一性問題,支持熱更新,做到了隨時(shí)隨地上線。

          提到 ReactNative,大家一定會(huì)和 Flutter 去做比較,F(xiàn)lutter 同樣是比較通用的跨端框架,兩者各有優(yōu)缺點(diǎn),圍繞著兩者之間的討論也挺多的,但對(duì)于開發(fā)者而言,在合適的場(chǎng)景中選擇合適的更重要,后面我們也會(huì)介紹在游戲中,我們是如何使用 ReactNative 完成一些活動(dòng)頁面的開發(fā)的。

          ReactNative 作為跨端框架在原生端 App 中使用比較多,從國外的 Facebook 到國內(nèi)各大大廠都在使用,而且基于該設(shè)計(jì)思想的跨端框架也不少,如 Weex 等,而在游戲中使用的還比較少,主要原因還是游戲的開發(fā)、運(yùn)行原理與原生差異太大。目前游戲的運(yùn)行環(huán)境有很多種,主要以 Unity、Cocos、UE4 為主,而且這些游戲平臺(tái)已經(jīng)具備了跨移動(dòng)端平臺(tái)的能力,同時(shí)支持 Android、iOS 等設(shè)備,且具備熱更新能力。

          在原生 App 開發(fā)中很多快速迭代的頁面都采用了 H5 開發(fā),主要集成、開發(fā)起來簡(jiǎn)單,游戲中也比較類似,這些 H5 頁面也做到了多平臺(tái)同時(shí)支持,但在響應(yīng)速度、啟動(dòng)速度、內(nèi)存等性能指標(biāo)上會(huì)顯得有點(diǎn)不足,而且在游戲環(huán)境中很難做到沉浸式的體驗(yàn)。所以圍繞著解決活動(dòng)快速迭代、發(fā)布、高性能、沉浸體驗(yàn)等問題,也做了不少解決方案,參考、學(xué)習(xí)這些經(jīng)驗(yàn)我們也做了大量的對(duì)比測(cè)試,在早期的方案上最終選定了 ReactNative 作為基礎(chǔ)引擎。

          游戲環(huán)境簡(jiǎn)介:
          • 自渲染引擎:現(xiàn)在的游戲一般都是基于 opengl 設(shè)計(jì),自建的 UI 渲染引擎,將 UI 內(nèi)容更新到原生的 surface 來顯示,所以和原生的 UI 組件體系差別較大,原生端的系統(tǒng)組件不再適用,且整個(gè)游戲在 Android 設(shè)備上是一個(gè) Activity,另外游戲自渲染引擎提供了很多動(dòng)畫屬性,來滿足高質(zhì)量的動(dòng)畫體驗(yàn)及沉浸式體驗(yàn),這些在原生側(cè)都是無法共享的。

          • 開發(fā)語言差異:在開發(fā)語言上也存在很大的差異(如 Unity C#/Lua 等),不同于 Android、iOS 的系統(tǒng)開發(fā)語言、IDE,相對(duì)客戶端,參與這方面的開發(fā)者也比較少,這也限制了很多原生框架在游戲中的使用,當(dāng)然游戲也是需要訪問設(shè)備的一些資源的,這就是常說的 bridge,游戲通過 bridge 來調(diào)用系統(tǒng)或者開發(fā)者提供的 API,UI 上仍無法直接共享,雖然網(wǎng)絡(luò)上也有一些紋理共享的方案打通游戲和原生 UI,但使用上仍然有很大的局限性。

          • 性能要求高:游戲相比于 app 來說對(duì)畫質(zhì)、渲染性能要求較高,這也導(dǎo)致了自身對(duì)內(nèi)存、CPU 占用較高,對(duì)于接入的業(yè)務(wù)、頁面的內(nèi)存峰值、穩(wěn)定值方面要求比較嚴(yán)格,最好能做到退出頁面即釋放。

          • 熱更能力強(qiáng):游戲一般都支持熱更能力,如 Unity,本身就支持 JavaScript 和 Lua 開發(fā),所以存在 unity+Lua 的熱更方式,且很多活動(dòng)或者游戲業(yè)務(wù)都會(huì)采用熱更和動(dòng)態(tài)入口方式,減少安裝包大小,提升靈活性。

          • 支持設(shè)備復(fù)雜:游戲的運(yùn)行環(huán)境除了常見的 Android、iOS 平臺(tái)外,還存在 PC、Android 模擬器等,所以在兼容性和體驗(yàn)上要求比常見的 app 要高。測(cè)試發(fā)現(xiàn)現(xiàn)有的 Android 模擬器一般都是采用 x86 架構(gòu),支持 32 及 64 位,而手機(jī)設(shè)備一般是 arm v7、v8,雖然模擬器也支持了 v7、v8 兼容模式,但都是通過 arm 轉(zhuǎn) intel 指令完成,實(shí)測(cè)存在很多兼容問題,支持起來難度比較很大。

          選擇 ReactNative

          從游戲端內(nèi)的數(shù)據(jù)來看,除了游戲本身核心外,一些活動(dòng)、功能都是需要快速迭代的,因此端內(nèi)用了很多 h5 的活動(dòng)場(chǎng)景,且為游戲提供的大量的 API 和數(shù)據(jù)能力,但在內(nèi)存、性能、沉浸式體驗(yàn)上與游戲仍有很大的差距;

          另外因游戲、H5 與原生端方案的差異,原生 UI 組件無法在游戲中直接使用,需要開發(fā)實(shí)現(xiàn),這點(diǎn)比較類似于 Flutter,所以為了能更好的兼容原生端的一些能力、場(chǎng)景,選擇能支持系統(tǒng) UI 交互、跨不同游戲平臺(tái),是我們選擇的首要考慮條件。

          從技術(shù)上來看,有游戲內(nèi)的解決方案,有客戶端的解決方案,在考慮選擇方案時(shí),我們主要考慮了以下幾個(gè)問題:

          1. 游戲擁有很多不同的平臺(tái),而且開發(fā)語言不一致,采用游戲端內(nèi)方案,就會(huì)涉及到維護(hù)多套引擎的問題,很難做到架構(gòu)統(tǒng)一性,比較流行的如 xLua、PureTS 等。


          2. 客戶端比較流行的跨端方案比較多,上面說的 h5 頁面就能很好的解決跨平臺(tái)問題,也是目前很多游戲活動(dòng)采用的解決方案,但因?yàn)槠湫阅?、體驗(yàn)與原生客戶端的差異,才有了后來 Facebook 對(duì)外開源的 ReactNative 方案,它很好的支持了統(tǒng)一的原生體驗(yàn),并大大提升了性能,引領(lǐng)了大前端的浪潮?,F(xiàn)如今發(fā)展比較迅速的 Flutter,自渲染引擎和 UI 一致性,也逐漸被很多大廠 App 采用;另外國內(nèi)友商也提出了自己的跨端方案 Weex,原理上與 ReactNative 類似。

          為什么沒有選擇 Flutter、Weex 作為我們游戲端跨端引擎呢?相比而言 Flutter 的工程化較為復(fù)雜、整體偏重,而且很難適應(yīng)游戲和活動(dòng)業(yè)務(wù)分離開發(fā)的場(chǎng)景,而 weex 因?yàn)樯鷳B(tài)與 ReactNative 的差距,也不在我們視角之內(nèi);另外游戲端內(nèi)的 xLua+Unity、及騰訊已開源的 pureTS 也是業(yè)內(nèi)用的比較多的方案,我們也一起做了對(duì)比分析:

          其中 xLua、PureTS 采用的是游戲端內(nèi)的 UI 渲染,在游戲內(nèi)部是比較成熟的方案,之所以不在我們前期的評(píng)估的范圍之內(nèi)的原因如下,也不是方案不好,而是不適合,當(dāng)然采用 ReactNative 原生端方案也有局限性,如 UI 無法和游戲混排,這也是為什么完成 ReactNative 搭建后,也開始持續(xù)迭代支持了 PureTS 方案的原因,具體原理這里就不解釋,這是一個(gè)開源項(xiàng)目,原理不算復(fù)雜:

          1. 兩者采用的是游戲 UI 組件,開發(fā)者必須對(duì)游戲本身的設(shè)計(jì)和架構(gòu)有很深的了解,比較適合有豐富游戲開發(fā)經(jīng)驗(yàn)的團(tuán)隊(duì),而我們是客戶端團(tuán)隊(duì)。


          2. 這些方案都是針對(duì)某個(gè)游戲平臺(tái)而設(shè)計(jì),不具體全平臺(tái)統(tǒng)一性,需要大量適配支持 Cocos、Unity、UE4 等平臺(tái),維護(hù)成本較高。


          3. 很難復(fù)用客戶端很多復(fù)雜的組件,例如地圖、直播、地圖等等的組件,這些在游戲中就不支持,自然這些方案也很難支持

          相信大家還是會(huì)有疑問,選擇 ReactNative 感覺不是一個(gè)最好的選擇,相比于 Flutter 的最近的突飛猛進(jìn)發(fā)展,ReactNative 遜色了太多,這兩年進(jìn)展微乎其微,而且渲染性能的瓶頸也越來越制約了其發(fā)展,先后有很多開發(fā)者都宣布不再開發(fā)、維護(hù) ReactNative,轉(zhuǎn)向原生開發(fā)或者 Flutter 的懷抱,但我們最終還是堅(jiān)定的選擇了 ReactNative,更看好其未來的架構(gòu)發(fā)展,詳細(xì)大家可以參考我的文章《庖丁解牛!深入剖析 React Native 下一代架構(gòu)重構(gòu)》,同時(shí)在后面的章節(jié)中,也會(huì)為大家重點(diǎn)講解新架構(gòu)的特點(diǎn)。

          ReactNative 在游戲營銷場(chǎng)景中的實(shí)踐

          上面已經(jīng)聊過游戲環(huán)境和 App 的差異了,也是因?yàn)檫@些特殊性,我們最初的方案采用了 ReactNative,官方標(biāo)準(zhǔn)的設(shè)計(jì)和腳手架工程可以幫助我們很好的搭建一個(gè) App,可以幫助開發(fā)者在不需要有原生客戶端開發(fā)的經(jīng)驗(yàn)的情況下,生成跨端的 App。但游戲不一樣,拿 Unity 的游戲來說,游戲的打包、開發(fā)環(huán)境是 Unity 的 IDE,另外游戲的頁面是自渲染的,如何在游戲中顯示原生的 UI,這些都是要解決的問題。

          總結(jié)下來要在游戲環(huán)境中運(yùn)行 ReactNative,要解決幾個(gè)問題:

          1. 工程化,快速支持 ReactNative 的調(diào)試和集成

          2. ReactNative 頁面容器,承載并管理 ReactNative 頁面

          3. 支持熱更新服務(wù),支持靈活、快速上線業(yè)務(wù)

          因整體原理不復(fù)雜,很多文章也做了很詳細(xì)的介紹,下面就簡(jiǎn)單說在游戲中的一些差異和思路

          1. 工程化
          • 在游戲中引入原生端的組件庫都是以 plugin 方式集成,所以首先要將引擎作為一個(gè) Module、Plugin 集成到游戲中,拿 Android 舉例,將 ReactNative sdk 封裝成獨(dú)立的 aar module,在游戲中引入這個(gè) aar 作為 Plugin,游戲的 Native 代碼能訪問我們 aar plugin,這點(diǎn)和原生開發(fā)其實(shí)是一致的。

          • 在游戲中很多頁面和游戲都是游戲中實(shí)現(xiàn)的,所以還需要解決游戲調(diào)用 native code 問題,比如我們需要在游戲中的某個(gè)按鈕打開 ReactNative 頁面,拿 unity 來說,就要實(shí)現(xiàn) c# 代碼到 ReactNative 代碼的調(diào)用,這里要封裝一層 bridge,這些都是標(biāo)準(zhǔn)的游戲 API,具體可以參考《淺談 Unity 與 Android 原生的橋接》,其他游戲平臺(tái)也比較類似。

          • Debug 也是開發(fā)調(diào)試中必要環(huán)境,需要在游戲中引入 debug 開關(guān)和入口,如懸浮窗等,并要做好 release 包關(guān)閉入口。

          2.ReactNative 頁面容器

          上面也介紹了游戲都是采用自繪引擎,所有交互都是在一個(gè) Activity 頁面中,任何新的頁面的跳轉(zhuǎn)都會(huì)導(dǎo)致游戲 pause 或者 stop,打斷其沉浸式體驗(yàn),而 ReactNative 是在 ReactRootView 中承載所有的 UI 渲染的,所以容器的設(shè)計(jì)思路考慮了以下幾種方案:

          • 將 ReactRootView 加載到游戲 Activity 的 Rootview 中,作為一個(gè)子 View,關(guān)閉頁面時(shí),從 Rootview 階段移除。

          • 將 ReactRootView 封裝到系統(tǒng)的 Dialog 窗口中,這樣既可以做到獨(dú)立窗口加載到游戲中,也不打斷游戲進(jìn)程。

          • 有了頁面容器后,跳轉(zhuǎn)不同功能的頁面,就需要制定一個(gè)協(xié)議了,通過協(xié)議完成頁面數(shù)據(jù)和功能的傳遞,可以參考開源的 Router 協(xié)議等。

          • 活動(dòng)頁面多了后,就涉及到頁面之間跳轉(zhuǎn)和窗口管理了,所以需要一套完善的窗口管理 API,并通過 Unity api,讓游戲可以快速通過 pop 協(xié)議或者指定 id 關(guān)閉頁面。

          以下是設(shè)計(jì)完成后大概能力介紹:

          3. 熱更新能力

          熱更新能力是 ReactNative 最基礎(chǔ)的能力,因引擎支持從 asset 目錄或者磁盤分區(qū)中加載 JS 文件,解決好加載路徑和包下載問題,就能很好的支持熱更新能力,其中包更新:

          • 考慮引擎的統(tǒng)一性,可以采用 native 的包下載機(jī)制

          • 游戲也支持資源更新,也可考慮將 js 文件作為資源更新

          • 熱更模式一般會(huì)支持 diff 更新、強(qiáng)更、非強(qiáng)更,這些都有比較成熟的框架,這里就不細(xì)述了

          4.Common API 設(shè)計(jì)

          在實(shí)際的業(yè)務(wù)開發(fā)工程中,僅僅靠 ReactNative 提供的基礎(chǔ) API 和組件是不夠的,比如網(wǎng)絡(luò)請(qǐng)求,大部分客戶端都會(huì)有網(wǎng)關(guān),標(biāo)準(zhǔn)的 API 基本無法滿足要求,這里就涉及到要封裝自己的 API 和組件的問題:

          • 基于 ReactNative 框架提供的 ReactBaseJavaModule,完成對(duì)一些公共 API 的封裝

          • 基于 ReactNative 提供的 ViewManager 框架,擴(kuò)展一些自定義的原生端組件

          但似乎這些還是不夠,因?yàn)槲覀兪窃谟螒颦h(huán)境中開發(fā),實(shí)際上游戲中或者游戲開發(fā)者也需要注入一些 API 到 ReactNative 中,供業(yè)務(wù)使用、擴(kuò)展,而上述的 ReactNative 的組件和 API 架構(gòu),對(duì)于不熟悉架構(gòu)的同學(xué)來說,會(huì)有相當(dāng)大的學(xué)習(xí)成本,所以我們基于 ReactNative,提出了 CommonModule 的架構(gòu)

          • 不依賴 ReactNative SDK,采用系統(tǒng)標(biāo)準(zhǔn)的數(shù)據(jù)結(jié)構(gòu)和 interface 實(shí)現(xiàn)

          • 提供標(biāo)準(zhǔn)的注冊(cè) API,將這些 interface 注入到 CommonModuleManager

          • 初始化 ReactPackge 時(shí),會(huì)根據(jù) CommonModule 生成對(duì)應(yīng)的 ReactBaseJavaModule,并完成注冊(cè)

          解決好上述的問題后,基礎(chǔ)的功能基本就覆蓋了,而且 API 可擴(kuò)展性強(qiáng),當(dāng)然除了這些外還是不夠的,還需要基于基礎(chǔ)版本不斷迭代,豐富組件、窗口管理、降級(jí)冗災(zāi)等,以下是我們?cè)谟螒蛑械耐暾軜?gòu)

          從架構(gòu)圖中我們可以看到,基本覆蓋了游戲活動(dòng)中需要用到各種 API 及各種自定義場(chǎng)景:

          • 沉浸式原生體驗(yàn),與游戲頁面活動(dòng)完美融合

          • 快速、完善的接入、開發(fā)、驗(yàn)收體驗(yàn)

          • 模版化的頁面搭建,跨平臺(tái)運(yùn)行

          • 業(yè)務(wù)活動(dòng)熱更上線,隨時(shí)、動(dòng)態(tài)、不發(fā)版上線

          ReactNative 的性能優(yōu)化

          隨著版本不斷迭代完善,基本具有大量上線游戲的能力,隨著游戲業(yè)務(wù)越來越多,在不同的游戲環(huán)境中,也碰到不少問題,這也從側(cè)面體現(xiàn)出了游戲場(chǎng)景和架構(gòu)的復(fù)雜性,主要核心問題還是在于 ReactNative 的沉浸式體驗(yàn)、啟動(dòng)性能、內(nèi)存、渲染性能問題等,似乎這些問題也是 ReactNative 的通病,為了解決這些問題,我們開始專項(xiàng)優(yōu)化。

          1. 啟動(dòng)性能優(yōu)化
          針對(duì)啟動(dòng)性能問題,我們也測(cè)試列大量數(shù)據(jù),ReactNative 在純客戶端 App 中,性能表現(xiàn)還算不錯(cuò),但在游戲低內(nèi)存、cpu 過度占用的情況下,該問題顯得格外突出,要解決這些問題,首先我們需要了解 ReactNative 加載的主要時(shí)間消耗,可以參考下圖:

          整體頁面渲染顯示前,需要首先加載加載初始化 React Native Core Bridge,主要包含 ReactNative 的運(yùn)行環(huán)境、UI 和 API 組件功能等,然后才能運(yùn)行業(yè)務(wù)的 JS,執(zhí)行 render 繪制 UI,完成后,React Native 才能將 JS 的組件渲染成原生的組件。因頁面的加載流程是固定不變的,所以我們可以采用了提前預(yù)加載 Core bridge 的方案來提升加載性能,當(dāng)游戲營銷頁面啟動(dòng)前,預(yù)先加載好原生端 bridge,這樣在打開業(yè)務(wù)是指需要運(yùn)行前端 JS 代碼渲染,設(shè)計(jì)思路上我們也根據(jù)業(yè)務(wù)場(chǎng)景設(shè)計(jì)了模式:

          • 預(yù)加載業(yè)務(wù)包:提前加載好完整的業(yè)務(wù)包到內(nèi)存,生成并緩存 ReactInstanceManager 對(duì)象,在業(yè)務(wù)啟動(dòng)時(shí),從內(nèi)存緩存中獲取該對(duì)象,并直接運(yùn)行綁定 rootview,經(jīng)過改造,該方案能提升整體的打開速度 30%-50% 左右,游戲環(huán)境下,手機(jī)設(shè)備基本都達(dá)到秒開,模擬器設(shè)備在 2s 內(nèi),但這種通過內(nèi)存換取速度的方法,在業(yè)務(wù)量大后,很明顯是不可取的,所以整包預(yù)加載的局限性比較強(qiáng)。

          • Common 包預(yù)加載:針對(duì)全包預(yù)加載的局限性,我們提出了分包方案,預(yù)加載 common 包,研究發(fā)現(xiàn) ReactNative 打包生成的業(yè)務(wù)包其實(shí)有兩部分內(nèi)容,一部分是公共的基礎(chǔ)組件、API 包,統(tǒng)稱 common 包,一部分是業(yè)務(wù)的核心邏輯包。改造打包方式,可以把原有的全包模式分離成 common+bussiness,在多業(yè)務(wù)包模式下,可以共享統(tǒng)一的 common 包,在打開業(yè)務(wù)前,我們會(huì)優(yōu)先預(yù)加載 common 包,并緩存對(duì)應(yīng)的 ReactInstanceManager 對(duì)象,用戶觸發(fā)打開業(yè)務(wù)后,再加載 bussiness 包,該方案相對(duì)于全包預(yù)加載性能略差,但比不預(yù)加載能提升 15%-20% 左右,同時(shí)支持多業(yè)務(wù)運(yùn)行環(huán)境,具體思路可以參考開源項(xiàng)目 react-native-multibundler

          • 從時(shí)序運(yùn)行上,除了 core bridge 的初始化外,js 運(yùn)行到頁面顯示,實(shí)際上也占用了不少時(shí)間,在預(yù)加載 core bridge 上,我們更近一步,支持了預(yù)加載 rootview,提前將要渲染頁面的 rootview 運(yùn)行起來緩存在內(nèi)存,當(dāng)然這里加載的還是基礎(chǔ)模塊,在業(yè)務(wù)打開時(shí),路由觸發(fā)展示頁面即可,可以做到頁面無延時(shí)打開,但是對(duì)內(nèi)存的開銷,比預(yù)加載 core bridge 更高。

          當(dāng)然上述方案都是通過內(nèi)存換性能,不同的加載方式都做到了云控,隨時(shí)切換、關(guān)閉。除了這些方案外同樣還有其他方式能優(yōu)化啟動(dòng)性能:

          1. Lazy module,將引擎自定義的 API Native Module 改造成懶加載方式,整體性能提升在 5% 左右。

          2. 業(yè)務(wù)代碼做到按需 require,不需要展示的部分,采用 lazy require,提升頁面的顯示、渲染速度。

          3. 裁剪業(yè)務(wù)包,將業(yè)務(wù)代碼沒有用到 React 的 module、API、組件刪除,減少業(yè)務(wù)包大小來提升啟動(dòng)性能。

          4. 分包方案,從測(cè)試數(shù)據(jù)來看,業(yè)務(wù)包越小,啟動(dòng)性能越好,包大小無法減小后,將業(yè)務(wù)包按照路由拆分為子包,也能立竿見影的解決啟動(dòng)速度問題。將業(yè)務(wù)包按照路由頁面和功能分成多個(gè)子的業(yè)務(wù)子包,讓首屏業(yè)務(wù)邏輯包變小,做到按需加載其他業(yè)務(wù)包,提升首頁啟動(dòng)性能。

          這些方案都從引擎加載的角度解決了啟動(dòng)性能慢,做到了按需加載,整體性能達(dá)到了最優(yōu)化。但是在游戲中,業(yè)務(wù)頁面的顯示還是太依賴服務(wù)度請(qǐng)求來完成頁面的渲染,所以在逐步優(yōu)化后,發(fā)現(xiàn)網(wǎng)絡(luò)請(qǐng)求對(duì)于頁面的顯示也占了很大一部分,為了進(jìn)一步提升首屏顯示,我們?cè)黾恿司W(wǎng)絡(luò)請(qǐng)求預(yù)拉取、圖片預(yù)緩沖方案:

          1. 網(wǎng)絡(luò)預(yù)拉取,對(duì)于一些對(duì)首屏顯示影響較大的網(wǎng)絡(luò)請(qǐng)求,在引擎加載后,在合適時(shí)機(jī)從云控平臺(tái)獲取后,根據(jù)配置拉取并緩存到內(nèi)存,打開業(yè)務(wù)后,優(yōu)先從緩存中讀取網(wǎng)絡(luò)接口內(nèi)容并顯示。

          2. 圖片預(yù)緩存,對(duì)于一些加載較慢的圖片,將鏈接配置到云端后,在合適時(shí)機(jī)提前預(yù)加載到 Fresco 內(nèi)存,頁面打開后 Fresco 會(huì)從緩存中直接讀取 bitmap

          除了這些方案外,替換 JSC 引擎到 hermes,也能很好的解決啟動(dòng)性能問題,后面章節(jié)會(huì)重點(diǎn)介紹。

          2. 內(nèi)存優(yōu)化 :

          以上所有的優(yōu)化更多是針對(duì)啟動(dòng)性能的優(yōu)化設(shè)計(jì),也是業(yè)內(nèi)用于提升加載性能的方案,在游戲的復(fù)雜環(huán)境下,除了性能外,對(duì)于內(nèi)存的要求也是很嚴(yán)格的,游戲啟動(dòng)后,本身對(duì)于內(nèi)存的消耗就比一般的原生 app 高,所以在內(nèi)存使用上會(huì)更精確和嚴(yán)格,那 ReactNative 是怎么優(yōu)化內(nèi)存的

          1. 分包方案,分包方案除了在啟動(dòng)速度上有很大優(yōu)化外,實(shí)現(xiàn)了按需加載,對(duì)于內(nèi)存來說也做到了最優(yōu)化。


          2. 字體加載,因游戲字體庫無法和原生字體共享,導(dǎo)致在 ReactNative 頁面使用字體會(huì)大大增加整體的內(nèi)存,為了降低字體的內(nèi)存,我們支持了字體的裁剪方案,按需打入字體,刪掉一些生僻的字,大大降低了字體包的大小。另外字體文件對(duì)于業(yè)務(wù)包大小影響也比較大,我們支持字體的動(dòng)態(tài)下發(fā)和加載。


          3. 圖片優(yōu)化,除了業(yè)務(wù) UI 和 JS 本身占用的內(nèi)存外,內(nèi)存上占用比較大的是圖片,而且圖片有緩存,為了降低圖片的內(nèi)存消耗,我們支持了 webp、gif 等格式的圖片,有損壓縮,同時(shí)對(duì)于網(wǎng)絡(luò)圖片做到了按手機(jī)分辨率下發(fā)。另外提供 API 到前端業(yè)務(wù),按需清理不使用的圖片,及時(shí)釋放內(nèi)存,并控制圖片緩存大小。

          3. 渲染性能:

          除了內(nèi)存、啟動(dòng)性能外,在游戲中的渲染性能也至關(guān)重要,ReactNative 受限于游戲內(nèi)的內(nèi)存和 CPU 負(fù)載高,同等復(fù)雜度頁面,表現(xiàn)不如原生 App。為了能優(yōu)化這些指標(biāo),我們對(duì) ReactNative 的渲染流程做了分析和優(yōu)化,支持靜止?fàn)顟B(tài)下幀率基本達(dá)到了 60fps,大致優(yōu)化如下:

          1. ReactNative 是前端事件驅(qū)動(dòng)原生 UI 渲染的,所以設(shè)計(jì)上 ReactNative 會(huì)在 Frame Buffer 每一幀繪畫結(jié)束后的回調(diào)在 UI 線程中處理 UI 更新,即使沒有更新的情況下也會(huì)空運(yùn)轉(zhuǎn),這在 UI 線程負(fù)載本就較高的游戲中,增加了 UI 的負(fù)擔(dān)


          2. 動(dòng)畫、點(diǎn)擊事件都是同樣的設(shè)計(jì),會(huì)不斷的有任務(wù)空轉(zhuǎn)占用 UI 線程,增加了 UI 線程每次繪制的時(shí)間


          3. 解決這個(gè)問題,就是要支持資源的按需加載,我們將動(dòng)畫、UI 更新事件放到了消息 map,每次一幀渲染完成后,我們會(huì)檢查 map 消息,是否有需要處理的消息,沒有后續(xù)就不再在一幀渲染完成后調(diào)度 UI 線程,當(dāng)用戶觸發(fā)了動(dòng)畫或者 UI 更新,會(huì)發(fā)送消息 map,并注冊(cè)幀渲染的 callback,在 callback 中檢查 map 消息更新 UI

          另外 ReactNative 采用的是原生 UI 渲染,在打開硬件加速的情況,整體渲染性能表現(xiàn)比較高,但是在游戲環(huán)境中,大部分游戲都是不開硬件加速的(自渲染組件和引擎的緣故),對(duì)于比較復(fù)雜的 ReactNative UI,更新 UI 時(shí)整體 FPS 會(huì)偏低,UI 響應(yīng)會(huì)比較慢,特別是在模擬器(限制 fps30)的情況下,渲染性能更加差強(qiáng)人意。在復(fù)雜交互的情況,要怎么提升性能?

          1. 簡(jiǎn)單的 UI 設(shè)計(jì),沒有大圖背景的情況下,不開硬件加速,整體渲染性還不算差,但有大的背景情況下,UI 性能表現(xiàn)尤其差,所以解決渲染問題,其實(shí)更多的是要解決大圖渲染的問題


          2. ReactNative 提供了 renderToHardwareTextureAndroid 來用 native 內(nèi)存換渲染的性能,導(dǎo)致的問題是內(nèi)存消耗較高,對(duì)于圖片不是太多、內(nèi)存限制不是很嚴(yán)格的業(yè)務(wù),可以采用該方式提升性能


          3. 對(duì)于大量使用圖片的業(yè)務(wù),我們?cè)O(shè)計(jì)一套采用 opengl 渲染方式的組件,支持紋理圖 (比較通用的 etc1),從內(nèi)存和渲染性能上,明顯都得到了很大的提升,但這種模式依賴硬件加速,所以一般是在 Dialog 窗口模式中使用

          /* GLES20.glCompressedTexImage2D(target, 0, ETC1.ETC1_RGB8_OES, bitmap.getWidth(), bitmap.getHeight(), 0, etc1tex.getData().capacity(), etc1tex.getData());*//* 

          -End-

          最近有一些小伙伴,讓我?guī)兔φ乙恍?nbsp;面試題 資料,于是我翻遍了收藏的 5T 資料后,匯總整理出來,可以說是程序員面試必備!所有資料都整理到網(wǎng)盤了,歡迎下載!

          點(diǎn)擊??卡片,關(guān)注后回復(fù)【面試題】即可獲取

          在看點(diǎn)這里好文分享給更多人↓↓

          瀏覽 46
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  男人天堂社区 | 欧美乱码 | 九九免费视屏 | 我要看亚洲黄色片一级 | 就爱操b网在线 |