前人種樹后人乘涼
原文地址
自從React Native出世扶供,雖然官方一直盡可能的優(yōu)化其性能,為了能讓其媲美原生App的速度奉瘤,但是現(xiàn)實感覺有點不盡人意。接下來介紹下實踐中遇到的一些性能問題以及優(yōu)化方案头镊。以下對性能參數(shù)的依據(jù)是來自于React Native自帶的FPS Monitor.
一、Navigator頁面切換動畫優(yōu)化
場景: 在Navigator還沒出來時魄幕,導(dǎo)航器是由NavigatorIOS來實現(xiàn)的,當(dāng)時覺得頁面切換動畫很流暢颖杏,但是一旦用Navigator后纯陨,發(fā)現(xiàn)定義的切換動畫會使JS線程出現(xiàn)嚴(yán)重的掉幀(卡頓現(xiàn)象)。
原因: NavigatorIOS的切換動畫是跑在UI主線程上留储,而不是JS線程上的翼抠,所以不受JS線程上的掉幀影響。當(dāng)然官方還是推薦使用Navigator,其原因如下:
- Navigator擴展性的API設(shè)計使得它完全可以通過js定制获讳,而NavigatorIOS則無js層面的定制阴颖;
- Navigator使用JavaScript編寫,iOS和Android都可以使用丐膝,而NavigatorIOS只能在IOS上量愧;
- Navigator優(yōu)化后的動畫效果還算不錯,而且官方還在不斷改進(jìn)中帅矗,當(dāng)然這個動畫比不上NavigatorIOS那么順滑偎肃。但NavigatorIOS并不在FaceBook的應(yīng)用中使用,也不是其主導(dǎo)開發(fā)浑此,而是開源社區(qū)主導(dǎo)開發(fā)累颂。所以可能坑多又沒人給出填坑的解決方法。
所以我們選擇導(dǎo)航的時候盡量選擇Navigator吧
Navigator在push到下一個頁面A時凛俱,如果A的componentDidMount方法里面做了耗時的操作紊馏,會發(fā)現(xiàn)丟幀的現(xiàn)象
Navigator的動畫是由JavaScript線程所控制的。想象一下“從右邊推入”這個場景的切換:每一幀中蒲犬,新的場景從右向左移動朱监,從屏幕右邊緣開始(不妨認(rèn)為是320單位寬的的x軸偏移),最終移動到x軸偏移為0的屏幕位置暖哨。切換過程中的每一幀赌朋,JavaScript線程都需要發(fā)送一個新的x軸偏移量給主線程。如果JavaScript線程卡住了篇裁,它就無法處理這項事情沛慢,因而這一幀就無法更新,動畫就被卡住了达布。
解決方法
使用API InteractionManager团甲,它的作用就是可以使本來JS的一些操作在動畫完成之后執(zhí)行,這樣就可確保動畫的流程性黍聂。
當(dāng)然這是在延遲執(zhí)行為代價上來獲得幀數(shù)的提高躺苦。
componentDidMount(){
InteractionManager.runAfterInteractions(() => {
this.fetchData();
});
}
二身腻、 組件響應(yīng)速度的優(yōu)化
場景:一個頁面包含多個類別的列表,由于列表都比較長匹厘,所以需要增加折疊功能并增加折疊動畫嘀趟,折疊按鈕使用的是TouchableHighlight組件。問題是當(dāng)我點擊折疊或者展開按鈕時出現(xiàn)延遲響應(yīng)和動畫掉幀的問題愈诚。
原因:在TouchableHighlight組件的onPress方法中執(zhí)行了setState的操作她按,由于列表的對象相對來說比較復(fù)雜需要大量計算的工作,所以導(dǎo)致了延遲響應(yīng)和JS線程的掉幀炕柔。
優(yōu)化問題:使用requestAnimationFrame(fn)在下一幀就立即執(zhí)行回調(diào)酌泰,這樣就可以異步來提高組件的響應(yīng)速度。而折疊動畫則可以使用LayoutAnimation一次性動畫來完成匕累,保證其流暢性陵刹。而對于某些狀態(tài)更新,setNativeProps方法可以讓我們直接修改原生視圖組件的屬性欢嘿,而不用通過setState來重新渲染結(jié)構(gòu)衰琐,這樣能使整個組件響應(yīng)速度變快。
onPress(){
this.requestAnimationFrame(()=>{
//onPress原本的操作
});
}
三际插、頁面加載與顯示優(yōu)化
場景:某些頁面需要訪問一個或多個業(yè)務(wù)數(shù)據(jù)服務(wù)碘耳,雖然取數(shù)據(jù)是異步,但是頁面總是會有一段較長的loading的時間框弛。
優(yōu)化問題:對于首屏所需的數(shù)據(jù)服務(wù)的訪問辛辨,使其在頁面加載階段盡早的發(fā)起數(shù)據(jù)請求,這樣有助于減少等待數(shù)據(jù)的時間瑟枫。而對長時間的Loading可能會降低用戶體驗的問題斗搞,我們可以使用Fake頁來提高用戶體驗。先顯示一個Fake頁慷妙,等數(shù)據(jù)請求后并執(zhí)行了相應(yīng)的業(yè)務(wù)邏輯后僻焚,再替換成真正的頁面。