Native與JavaScript交互原理圖
卡頓的場景
rn應(yīng)用界面的渲染是js驅(qū)動native完成的粘拾。js代碼運(yùn)行在javascript線程中城菊, react-native組件的生命周期硫眨、api調(diào)用、觸摸事件的處理等就是在這個線程上執(zhí)行的冯遂;在復(fù)雜應(yīng)用的root組件中拟枚,調(diào)用this.setState,觸發(fā)子組件重新渲染吼渡,而這個過程很耗資源容为,容易引發(fā)卡頓。
js->native
路由切換操作:添加一個新的路由寺酪,Javascript線程需要讀取這個場景所需要的所有組件坎背,然后通過適當(dāng)?shù)拿畎l(fā)送給本地端,創(chuàng)建視圖寄雀。這個過程會花費(fèi)多個幀得滤,引起卡頓。
這是因?yàn)閠ransition是由Javascript控制的盒犹。由此組件會在componentDidMount中做額外的計(jì)算懂更,這可能會導(dǎo)航在transition卡頓的第二個原因.
native->js
響應(yīng)觸摸事件:界面發(fā)生的事件是native轉(zhuǎn)發(fā)到j(luò)s的。如果此時js正在執(zhí)行耗時任務(wù)急膀,那么就來不及響應(yīng)這個事件沮协。例如可能出現(xiàn)點(diǎn)擊TouchableOpacity包裹的View時,透明度發(fā)生了變化卓嫂,但js端的響應(yīng)事件卻相對滯后慷暂。
卡頓的規(guī)避措施
場景一
Slow navigator transitions Navigator動畫由Javascript線程控制,轉(zhuǎn)換過程的每一幀晨雳,Javascript thread需要將新的x位置發(fā)送給主線程行瑞。如果javascript 線程被凍結(jié)。它就不能做這些餐禁,那么這些幀就不會被更新蘑辑,動畫就變得斷斷續(xù)續(xù)。
一勞永逸的解決方案是將基于 Javascript的動畫轉(zhuǎn)變?yōu)榛趍ain thread的動畫 useNativeDriver 其他情況應(yīng)該使用InteractionManager坠宴,為新的scene選擇最少的內(nèi)容數(shù)量以及動畫過程洋魂。
在相同的時間里,Javascript線程上做了大量的工作,導(dǎo)致幀被刪除副砍;如果在動畫期間衔肢,有大量的延遲類的工作,則可以考慮LayoutAnimation豁翎。Animated api當(dāng)前計(jì)算每一幀都是基于Javascript線程角骤,而LayoutAnimation利用了核心動畫,不會受到JS線程和主線程丟幀的影響LayoutAnimtion僅適用于fire-and-forget動畫(“靜態(tài)”動畫) - 如果動畫需要被中斷心剥,則你需要使用Animated邦尊。
場景二
在一個sceen里,移動一個View(Scrolling, translating, rotating), UI線程掉幀优烧。常見于蝉揍,帶透明背景的文本,在一個圖片之上畦娄∮终矗或者它的alpha混合的情況∥蹩ǎ可以使用shouldRasterizeIOS和renderToHardwareTextureAndroid來改進(jìn)性能杖刷。但最好不要亂用它,否則你的內(nèi)存會被用完驳癌,在使用這個屬性時滑燃,最好監(jiān)控性能和內(nèi)存的使用。如果你不計(jì)劃移動一個View, 則把這些屬性關(guān)閉颓鲜。
場景三
改變一個圖片大小的動畫不瓶,UI線程掉幀。在iOS, 每一次你調(diào)整一個圖片組件的寬和高灾杰,它都是從原始圖片中re-croped and scaled蚊丐。這個過程非常昂貴,特別是對于大圖來說艳吠。代替的麦备, 我們可以使用transform: [{scale}]樣式屬性動畫的改變大小,比如輕觸一個圖片昭娩,然后變?yōu)槿痢?/p>
場景四
My TouchableX view isn’t very responsive凛篙。有時,如果我們在相同的幀里改變透明度和顏色栏渺,以響應(yīng)觸摸事情呛梆。我們可能在onPress返回之后看不到作何的響應(yīng)。如果onPress里有一個setState, 它引發(fā)大量的工作磕诊,并且有一些幀被刪除掉填物,這時就會出現(xiàn)這種情況纹腌。一種解決方案是,將作何的動畫包裝在requestAnimationFrame處理器中滞磺。