RN-性能優(yōu)化 (二)

前人種樹后人乘涼
原文地址

自從React Native出世,雖然官方一直盡可能的優(yōu)化其性能,為了能讓其媲美原生App的速度,但是現(xiàn)實(shí)感覺有點(diǎn)不盡人意。接下來介紹下實(shí)踐中遇到的一些性能問題以及優(yōu)化方案。以下對(duì)性能參數(shù)的依據(jù)是來自于React Native自帶的FPS Monitor.

一、Navigator頁面切換動(dòng)畫優(yōu)化

場(chǎng)景: 在Navigator還沒出來時(shí),導(dǎo)航器是由NavigatorIOS來實(shí)現(xiàn)的,當(dāng)時(shí)覺得頁面切換動(dòng)畫很流暢,但是一旦用Navigator后,發(fā)現(xiàn)定義的切換動(dòng)畫會(huì)使JS線程出現(xiàn)嚴(yán)重的掉幀(卡頓現(xiàn)象)。

原因: NavigatorIOS的切換動(dòng)畫是跑在UI主線程上,而不是JS線程上的,所以不受JS線程上的掉幀影響。當(dāng)然官方還是推薦使用Navigator,其原因如下:

  • Navigator擴(kuò)展性的API設(shè)計(jì)使得它完全可以通過js定制,而NavigatorIOS則無js層面的定制;
  • Navigator使用JavaScript編寫,iOS和Android都可以使用,而NavigatorIOS只能在IOS上;
  • Navigator優(yōu)化后的動(dòng)畫效果還算不錯(cuò),而且官方還在不斷改進(jìn)中,當(dāng)然這個(gè)動(dòng)畫比不上NavigatorIOS那么順滑。但NavigatorIOS并不在FaceBook的應(yīng)用中使用,也不是其主導(dǎo)開發(fā),而是開源社區(qū)主導(dǎo)開發(fā)。所以可能坑多又沒人給出填坑的解決方法。

所以我們選擇導(dǎo)航的時(shí)候盡量選擇Navigator吧

Navigator在push到下一個(gè)頁面A時(shí),如果A的componentDidMount方法里面做了耗時(shí)的操作,會(huì)發(fā)現(xiàn)丟幀的現(xiàn)象

Navigator的動(dòng)畫是由JavaScript線程所控制的。想象一下“從右邊推入”這個(gè)場(chǎng)景的切換:每一幀中,新的場(chǎng)景從右向左移動(dòng),從屏幕右邊緣開始(不妨認(rèn)為是320單位寬的的x軸偏移),最終移動(dòng)到x軸偏移為0的屏幕位置。切換過程中的每一幀,JavaScript線程都需要發(fā)送一個(gè)新的x軸偏移量給主線程。如果JavaScript線程卡住了,它就無法處理這項(xiàng)事情,因而這一幀就無法更新,動(dòng)畫就被卡住了。

解決方法

使用API InteractionManager,它的作用就是可以使本來JS的一些操作在動(dòng)畫完成之后執(zhí)行,這樣就可確保動(dòng)畫的流程性。

當(dāng)然這是在延遲執(zhí)行為代價(jià)上來獲得幀數(shù)的提高。

componentDidMount(){
   InteractionManager.runAfterInteractions(() => {
     this.fetchData();
   });
}

二、 組件響應(yīng)速度的優(yōu)化

場(chǎng)景:一個(gè)頁面包含多個(gè)類別的列表,由于列表都比較長,所以需要增加折疊功能并增加折疊動(dòng)畫,折疊按鈕使用的是TouchableHighlight組件。問題是當(dāng)我點(diǎn)擊折疊或者展開按鈕時(shí)出現(xiàn)延遲響應(yīng)和動(dòng)畫掉幀的問題。

原因:在TouchableHighlight組件的onPress方法中執(zhí)行了setState的操作,由于列表的對(duì)象相對(duì)來說比較復(fù)雜需要大量計(jì)算的工作,所以導(dǎo)致了延遲響應(yīng)和JS線程的掉幀。

優(yōu)化問題:使用requestAnimationFrame(fn)在下一幀就立即執(zhí)行回調(diào),這樣就可以異步來提高組件的響應(yīng)速度。而折疊動(dòng)畫則可以使用LayoutAnimation一次性動(dòng)畫來完成,保證其流暢性。而對(duì)于某些狀態(tài)更新,setNativeProps方法可以讓我們直接修改原生視圖組件的屬性,而不用通過setState來重新渲染結(jié)構(gòu),這樣能使整個(gè)組件響應(yīng)速度變快。

onPress(){
   this.requestAnimationFrame(()=>{
        //onPress原本的操作
   });
}

三、頁面加載與顯示優(yōu)化

場(chǎng)景:某些頁面需要訪問一個(gè)或多個(gè)業(yè)務(wù)數(shù)據(jù)服務(wù),雖然取數(shù)據(jù)是異步,但是頁面總是會(huì)有一段較長的loading的時(shí)間。

優(yōu)化問題:對(duì)于首屏所需的數(shù)據(jù)服務(wù)的訪問,使其在頁面加載階段盡早的發(fā)起數(shù)據(jù)請(qǐng)求,這樣有助于減少等待數(shù)據(jù)的時(shí)間。而對(duì)長時(shí)間的Loading可能會(huì)降低用戶體驗(yàn)的問題,我們可以使用Fake頁來提高用戶體驗(yàn)。先顯示一個(gè)Fake頁,等數(shù)據(jù)請(qǐng)求后并執(zhí)行了相應(yīng)的業(yè)務(wù)邏輯后,再替換成真正的頁面。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容