原欄目|居玉溪

Qunar.com移動建筑集團前端工程師。從事平臺技術服務設施建設,庫納react Native的開發(fā)者主要負責現(xiàn)階段統(tǒng)一解決方案Ykit的前端建設。

歡迎來到團隊博客ymfe.tech,了解更多關于尖端技術的信息。

過去一年,去哪兒大規(guī)模應用React Native(簡稱RN)。結合業(yè)務本身的需求,我們基于RN-去哪兒React Native(簡稱QRN)提供了一套更適合去哪兒的解決方案。它包括公共包和業(yè)務包的拆分,組件和API的重新打包,以及各種提高開發(fā)效率的插件。

對于移動設備上的長名單,首屏渲染速度和內存恢復一直是我們關注的問題。ListView是RN提供的列表組件,類似RecyclerView和UITableView,采用漸進式渲染。也就是說,僅呈現(xiàn)用戶可視區(qū)域中的元素,并且可視區(qū)域中的元素根據(jù)位置偏移來更新。

1.React Native ListView性能優(yōu)化實踐1.1 RN ListView實現(xiàn)原理

RN ListView與RecyclerView、UITableView在無盡列表處理上不同,即沒有真正的復用節(jié)點,只是將元素從其父組件中移除出視口,從而釋放內存。移除的元素將仍然存在于虛擬樹中,并且列表中每個項目的引用將被保存。

上圖顯示了RN ListView在第一屏和渲染到100行時的元素統(tǒng)計。紅色方框中標記的數(shù)字,上面一個代表可視區(qū)域中的元素數(shù)量,下面一個代表虛擬樹中的元素數(shù)量。可以看到,從第一屏到100行,虛擬樹中的節(jié)點隨著新元素的渲染而增加。

RN ListView的主要目的是保存每行的狀態(tài),加快渲染元素的重渲染。這一點在克里斯托弗·切多(RN的核心開發(fā)者之一)身上已經(jīng)說得很清楚了。

1.2 rn listview的性能如何

這里我們從滑動體驗、記憶占用、位置跳躍能力三個方面來評價RN ListView的表現(xiàn)。

在滑動體驗方面,我用上圖中的列表在iPhone 5S中進行測試。RN ListView的幀數(shù)基本可以保持在55~60 fps,一般比較流暢。

和前面的例子一樣,在內存占用方面,從上表可以看出,隨著列表內容的不斷增加,其內存占用迅速增加。在無盡列表的場景中,應用程序可能會因為過度占用內存而崩潰,這是我們無法接受的。

位置跳轉的能力是指在某些場景下,列表需要瞬間跳轉到某個位置,比如通過通訊錄中的首字母跳轉。在RN ListView中,由于布局系統(tǒng)是由RN控制的,所以需要知道每一行從起點到終點的高度,才能準確的渲染出指定的位置。所以跳轉到未知區(qū)域時,必須先渲染起點和終點之間的所有元素,會造成一段時間的白屏,所以RN ListView在這個場景中的體驗不夠好。

1.3 qrn listview是如何優(yōu)化的?1.3.1 QRN列表視圖原則

為了解決注冊護士列表視圖的性能問題,我們引入了QRN列表視圖。它不采用與RN ListView相同的維護元素引用的方式,而是在React渲染列表時通過虛擬樹機制實現(xiàn)元素重用。

首先,介紹了如何使用React渲染列表:React要求列表中的每個項目都有一個關鍵屬性,該屬性將在React的虛擬樹diff過程中用作每個項目的標識符。

在上圖中,我們假設包裝器是列表的容器,組件是列表中的一個項目。當列表從左狀態(tài)切換到右狀態(tài)時,React會認為鍵為{1}的項目已被移除,鍵為{6}的項目已被添加,因此總共執(zhí)行了一次銷毀操作和一次創(chuàng)建操作。

我們稍微修改了一下前面的情況(如上圖)。此時,React會認為key={1}的項目已經(jīng)改變了位置,所以只會更新它,從而達到重用我們節(jié)點的目的。

按照這個思路,QRN的具體實施如上圖所示。當一些項目移出可視區(qū)域時,它們的鍵被分配給要創(chuàng)建的行。

1.3.2 QRN列表視圖性能

這里我們還是從前面三個方面來評價QRN ListView的表現(xiàn),即滑動體驗、記憶占用和位置跳躍能力。

根據(jù)相同條件下iPhone 5S中的測試結果。QRN ListView的幀數(shù)在30~40 fps左右。經(jīng)過調查,我們發(fā)現(xiàn)影響性能的主要原因是16 ms內渲染一幀時間過長。

在內存占用方面,從上表可以看出,隨著列表內容的增加,QRN ListView的內存基本穩(wěn)定。RN ListView內存增長太快。

和RN ListView一樣,它需要知道起點和終點之間每一條線的高度,才能準確的渲染出指定的位置。所以QRN ListView在這種場景下的體驗是不夠好的。

1.4特定場景的優(yōu)化-qrn無限列表視圖

由于RN的布局機制,無法從純JS層面完美解決位置跳轉,所以我們決定針對具體場景進行優(yōu)化。通過與實際業(yè)務應用的接觸,我們發(fā)現(xiàn)列表組件主要有兩種使用場景。

一種是上圖左側的情況,每一行的行高可能是不確定的,通過用戶連續(xù)滑動逐漸加載新內容,一般不會出現(xiàn)跳轉到還沒有渲染的位置的情況。另一種是右邊的情況,通常是通訊錄或者城市列表。每一行的高度都是固定的,需要有按位置跳的能力。

因此,我們在固定行高的場景中提出了一個深度優(yōu)化的QRN InfiniteListView組件。

1.4.1固定高度場景可以做哪些優(yōu)化?

在可變高度的情況下,渲染一條線時,必須先渲染前一條線并獲得其高度和位置,然后才能繼續(xù)渲染。但是,固定高度列表可以同時在多行中呈現(xiàn)和重用。原理如下:

1.4.2 QRN InfiniteListView性能

QRN InfiniteListView的性能還是從以上三個方面來評價的,分別是滑動體驗、內存占用和位置跳轉能力。

根據(jù)相同條件下iPhone 5S中的測試結果。QRN InfiniteListView的幀數(shù)可以保持在55~60 fps。所以可以說幀率比QRN ListView有了很大的提升。

在內存占用方面,從上表可以看出RN InfiniteListView的內存增長緩慢。由于QRN ListView和QRN ListView一樣,采用了元素復用的方式,所以內存恢復取得了很好的效果。

在位置跳轉方面,由于每一行的高度和位置都可以通過計算直接得到,所以滾動到任意位置都可以正確的呈現(xiàn)內容。

1.4.3場景的擴展

即使在一些高度不等的場景中,行高也是可以確定的,比如一個只有幾類內容的列表。此時,我們可以通過一個界面來指定行高。

1(rowData, rowIndex) => number

所以InfintiteListView可以覆蓋除行高完全未知以外的大部分列表場景。

1.5總結

通過比較上述三個列表組件,我們可以得出結論,QRN InfiniteListView最符合我們的性能要求,但它僅限于特定的場景。但也給了我們一個性能優(yōu)化的思路,就是當我們不能考慮所有的平臺和場景時,可以針對一些特定的場景進行優(yōu)化。最近在繼續(xù)優(yōu)化列表組件,會提供更好的解決方案,會繼續(xù)關注列表性能。

1.《listview的優(yōu)化 【YMFE】React Native ListView 性能優(yōu)化實踐》援引自互聯(lián)網(wǎng),旨在傳遞更多網(wǎng)絡信息知識,僅代表作者本人觀點,與本網(wǎng)站無關,侵刪請聯(lián)系頁腳下方聯(lián)系方式。

2.《listview的優(yōu)化 【YMFE】React Native ListView 性能優(yōu)化實踐》僅供讀者參考,本網(wǎng)站未對該內容進行證實,對其原創(chuàng)性、真實性、完整性、及時性不作任何保證。

3.文章轉載時請保留本站內容來源地址,http://f99ss.com/jiaoyu/1607148.html