前人種樹后人乘涼
原文地址
你需要了解什么是幀
在你的祖父輩佳窑,它們一般把視頻稱為”移動的圖片”的一個原因是:視頻中逼真的動作是以固定的速度蟋字,快速改變靜態(tài)的圖片創(chuàng)造出來一個錯覺。這里的每一個圖片就一個是幀。每一秒中圖片的數(shù)量(幀)约巷,它直接影響了視頻的真時性(或者app中的用戶界面). iOS的設(shè)備是每秒60幀记某。它也就給了你以及UI系統(tǒng)大約16.67毫秒的時間司训,來完成生成一張靜態(tài)圖片(幀)的所有工作。如果你不能在16.67ms內(nèi)完成液南,則你將會丟失一個幀壳猜,UI會出現(xiàn)無響應(yīng)狀態(tài)。
在你的應(yīng)用程序中滑凉,打開Deveroper菜單统扳,并切換到fps監(jiān)視器,你會發(fā)現(xiàn)有兩種不同的幀速率畅姊。
Javascript 幀速率
許多的React Native應(yīng)用咒钟,你的業(yè)務(wù)邏輯都是運行在JavaScript線程上的。比如React 應(yīng)用的生命周期(mount, update), API調(diào)用若未,觸摸事件的處理等朱嘴。并且在每一幀失效前, 更新原生支持的視圖(Views)是被成批處理的,并且在每一次事件循環(huán)遍歷結(jié)束后陨瘩,發(fā)送給本地端腕够。如果Javascript線程對于一個幀沒有響應(yīng),則被認為刪除這個幀舌劳。舉例來說,在一個復雜的應(yīng)用的root 組件中玫荣,你調(diào)用了this.setState. 它會導致重新宣染子組件甚淡,這個過程很消耗資源⊥背В可以假設(shè)為它將花費200ms, 那么導致12幀丟棄(200ms / 16.67ms)贯卦。通過Javascript控制的作何動畫,在這個過程會被凍結(jié)焙贷。如果作何計算超過100ms, 用戶就可以感受到撵割。
當你添加一個新的路由,Javascript線程需要讀取這個場景所需要的所有組件辙芍,然后通過適當?shù)拿畎l(fā)送給本地端啡彬,創(chuàng)建視圖。這個過程會花費多個幀故硅,引起卡頓庶灿,這是因為transition是由Javascript控制的。有此組件會在componentDidMount中做額外的計算吃衅,這可能會導航在transition卡頓的第二個原因.
另一個例子是響應(yīng)觸摸:如果你要做的任務(wù)在Javascript線程上跨越多個幀往踢,你可能會注意到TouchableOpacity的延遲。這就是在Javascript 線程在忙的時候徘层,不能處理從主線程發(fā)送過來的觸摸事件的原因峻呕,所以會出現(xiàn)利职,native view調(diào)整了透明度,而又不對觸摸事件做出響應(yīng)瘦癌。
InteractionManager.runAfterInteractions(() => {
do something...
});
一眼耀、Console.log 語句
當運行一個打包好的app, Console.log語句會引起很大的瓶頸。它會包含調(diào)試庫redux-logger, 所以在打包前佩憾,確保刪除了Console.log語句.
二哮伟、ListView初始化時或者讀取一個大的列表時很慢
我們可以通過以下的幾個方面,改善部分性能
?initialListSize
這個屬性用來指定我們第一次渲染時妄帘,要讀取的行數(shù)楞黄。如果我們想盡可能的快,我們可以設(shè)置它為1, 然后可以在后續(xù)的幀中抡驼,填棄其它的行鬼廓。每一次讀取的行數(shù),由pageSize決定.pageSize**pageSize
在使用了initialListSize之后致盟,ListView根據(jù)pageSize來決定每一幀讀取的行數(shù)碎税,默認值為1, 但如果你的的views 非常的小,并且讀取時占的資源很少, 你可以調(diào)整這個值馏锡,在找到適合你的值雷蹂。scrollRenderAheadDistance
“以像素為單位,如何預(yù)讀取要加載的行杯道?”
如果我們的列表有2000個項匪煌,而讓它一次性讀取,它會導致內(nèi)存和計算資源的耗盡党巾。所以scrollRenderAhead distance可以指定萎庭,超出當前視口多省,繼續(xù)宣染齿拂。removeClippedSubviews
“當它設(shè)置為true時驳规,當本地端的superview為offscreen時 ,不在屏幕上顯示的子視圖offscreen(它的overflow的值為hidden) 會被刪除署海。它可以改善長列表的滾動的性能吗购,默認值為true.
這對于大的ListViews來說是一個非常重要。在Android, overflow的值通常為hidden. 所以我們并不需要擔心它的設(shè)置叹侄,但是對于iOS來說巩搏,你需要設(shè)置row Container的樣式為overflow: hidden