《React Native痛點(diǎn)解析之性能調(diào)優(yōu)》要點(diǎn):
本文介紹了React Native痛點(diǎn)解析之性能調(diào)優(yōu),希望對(duì)您有用。如果有疑問(wèn),可以聯(lián)系我們。
自從React Native出世,雖然官方一直盡可能的優(yōu)化其性能,為了能讓其媲美原生App的速度,但是現(xiàn)實(shí)感覺(jué)有點(diǎn)不盡人意.接下來(lái)介紹下實(shí)踐中遇到的一些性能問(wèn)題以及優(yōu)化方案.以下對(duì)性能參數(shù)的依據(jù)是來(lái)自于React Native自帶的FPS Monitor.
場(chǎng)景: 在Navigator還沒(méi)出來(lái)時(shí),導(dǎo)航器是由NavigatorIOS來(lái)實(shí)現(xiàn)的,當(dāng)時(shí)覺(jué)得頁(yè)面切換動(dòng)畫(huà)很流暢,但是一旦用Navigator后,發(fā)現(xiàn)定義的切換動(dòng)畫(huà)會(huì)使JS線程出現(xiàn)嚴(yán)重的掉幀(卡頓現(xiàn)象).
原因: NavigatorIOS的切換動(dòng)畫(huà)是跑在UI主線程上,而不是JS線程上的,所以不受JS線程上的掉幀影響.當(dāng)然官方還是推薦使用Navigator,其原因如下:
Navigator擴(kuò)展性的API設(shè)計(jì)使得它完全可以通過(guò)js定制,而NavigatorIOS則無(wú)js層面的定制;
Navigator使用JavaScript編寫(xiě),iOS和Android都可以使用,而NavigatorIOS只能在IOS上;
Navigator優(yōu)化后的動(dòng)畫(huà)效果還算不錯(cuò),而且官方還在不斷改進(jìn)中,當(dāng)然這個(gè)動(dòng)畫(huà)比不上NavigatorIOS那么順滑.但NavigatorIOS并不在FaceBook的應(yīng)用中使用,也不是其主導(dǎo)開(kāi)發(fā),而是開(kāi)源社區(qū)主導(dǎo)開(kāi)發(fā).所以可能坑多又沒(méi)人給出填坑的解決辦法.
所以我們選擇導(dǎo)航的時(shí)候盡量選擇Navigator吧.
優(yōu)化切換動(dòng)畫(huà)卡頓的問(wèn)題:
使用API InteractionManager,它的作用就是可以使本來(lái)JS的一些操作在動(dòng)畫(huà)完成之后執(zhí)行,這樣就可確保動(dòng)畫(huà)的流程性.當(dāng)然這是在延遲執(zhí)行為代價(jià)上來(lái)獲得幀數(shù)的提高.
使用LayoutAnimation API(一次性動(dòng)畫(huà)),在對(duì)動(dòng)畫(huà)中途無(wú)取消要求或者其他中途回調(diào)要求的(比如局部組件特定顯示暗藏動(dòng)畫(huà)等),則可以使用這個(gè)方案.我們可以在調(diào)用setState之前,調(diào)用LayoutAnimation方法.代碼如下:
場(chǎng)景:基本上每個(gè)頁(yè)面都需要加載和渲染數(shù)據(jù),如果頁(yè)面列表數(shù)據(jù)結(jié)構(gòu)復(fù)雜,有時(shí)刷新數(shù)據(jù)時(shí)state中的未必有修改,但是遇到這樣的語(yǔ)句this.setState({data:samedata}) ,界面卻被重新render.
原因:這是react-native的生命周期,當(dāng)你調(diào)用setState時(shí),總是會(huì)觸發(fā)render的辦法.
優(yōu)化數(shù)據(jù)問(wèn)題:可以使用shouldComponentUpdate生命周期辦法,此辦法作用是在props或 者state改變且接收到新的值時(shí),則在要render辦法之前調(diào)用.此辦法在初始化渲染的時(shí)候不會(huì)調(diào)用,在使用forceUpdate辦法的時(shí)候也不會(huì).所以在這個(gè)辦法中我們可以增加些判斷規(guī)則來(lái)避免當(dāng)state或者props沒(méi)有改變時(shí)所造成的重新render.
但僅僅做這層判斷是不夠的,如果是一個(gè)列表的對(duì)象,例如下面的例子:
這里即使使用了shouldComponentUpdate中的判斷,但卻一直返回true,導(dǎo)致還會(huì)執(zhí)行render.所以必須對(duì)對(duì)象所有的鍵值進(jìn)行進(jìn)行比較才能確認(rèn)是否相等.這里推薦使用facebook自家的immutablejs.一個(gè)不可變數(shù)據(jù)類型的庫(kù).使用后可以直接使用一下的寫(xiě)法達(dá)到我們之前的目的(即使是對(duì)象都可以完美的做比較).修改后代碼如下:
immutablejs其他的具體用法請(qǐng)見(jiàn):http://facebook.github.io/immutable-js/
場(chǎng)景:在首屏頁(yè)面加載時(shí),加載前6分鐘的數(shù)據(jù)分6頁(yè)顯示,并需保持當(dāng)前選擇頁(yè)的時(shí)間的前6分鐘,如果依照此場(chǎng)景開(kāi)發(fā)所遇到問(wèn)題是:首頁(yè)加載時(shí)間太長(zhǎng),加載新數(shù)據(jù)時(shí)頁(yè)面顯示加載用戶體驗(yàn)不順暢.
原因:首頁(yè)哀求數(shù)據(jù)量過(guò)大,導(dǎo)致首屏頁(yè)面加載很慢;后臺(tái)數(shù)據(jù)更新時(shí)導(dǎo)致用戶體驗(yàn)不順暢.
優(yōu)化問(wèn)題:減少首屏加載的數(shù)據(jù),實(shí)現(xiàn)數(shù)據(jù)懶加載,其先加載3頁(yè)的數(shù)據(jù)量,然后在滑動(dòng)的時(shí)候后臺(tái)去取后面的數(shù)據(jù)(例如綁定到Slider組件的onMomentumScrollEnd事件中,每次取3條數(shù)據(jù)),最后每次保持6分鐘的數(shù)據(jù)在組件中,其他數(shù)據(jù)則可放到localstorage中作為緩存.這樣就可以減少首屏加載事件和提高用戶體驗(yàn).加載數(shù)據(jù)的滾動(dòng)列表示例代碼如下:
初始化(定義數(shù)據(jù)data):
滾動(dòng)列表的事件:分為左滑每次到3的倍數(shù)頁(yè)面取當(dāng)前取過(guò)的數(shù)據(jù)的前3分鐘的歷史數(shù)據(jù);右滑則取之后的時(shí)間.
場(chǎng)景:一個(gè)頁(yè)面包括多個(gè)類別的列表,由于列表都比較長(zhǎng),所以需要增加折疊功能并增加折疊動(dòng)畫(huà),折疊按鈕使用的是TouchableHighlight組件.問(wèn)題是當(dāng)我點(diǎn)擊折疊或者展開(kāi)按鈕時(shí)出現(xiàn)延遲響應(yīng)和動(dòng)畫(huà)掉幀的問(wèn)題.
原因:在TouchableHighlight組件的onPress辦法中執(zhí)行了setState的操作,由于列表的對(duì)象相對(duì)來(lái)說(shuō)比較復(fù)雜需要大量計(jì)算的工作,所以導(dǎo)致了延遲響應(yīng)和JS線程的掉幀.
優(yōu)化問(wèn)題:使用requestAnimationFrame(fn)在下一幀就立即執(zhí)行回調(diào),這樣就可以異步來(lái)提高組件的響應(yīng)速度.而折疊動(dòng)畫(huà)則可以使用LayoutAnimation一次性動(dòng)畫(huà)來(lái)完成,保證其流暢性.而對(duì)于某些狀態(tài)更新,setNativeProps辦法可以讓我們直接修改原生視圖組件的屬性,而不用通過(guò)setState來(lái)重新渲染結(jié)構(gòu),這樣能使整個(gè)組件響應(yīng)速度變快.
還有要提醒的是盡量?jī)?yōu)化組件的View結(jié)構(gòu),當(dāng)View的層級(jí)很深時(shí)渲染的速度也會(huì)變慢
場(chǎng)景:這里說(shuō)的資源包括React Native打出來(lái)的Bundle,圖片等靜態(tài)資源.RN的一股腦兒的打包方式,無(wú)疑一下子增大了Bundle包大小.還有一個(gè)頁(yè)面多多少少會(huì)包括一些圖片,特別是在一些商業(yè)APP中,圖片是對(duì)內(nèi)容一種補(bǔ)充,能讓提高用戶體驗(yàn).為了能更快的加載圖片,可以把圖片打入包中,當(dāng)然這個(gè)代價(jià)是巨大的.對(duì)APP來(lái)說(shuō),控制包的Size不管從商業(yè)方面還是開(kāi)發(fā)性能方面都是一個(gè)很重要的參數(shù).
優(yōu)化問(wèn)題:
對(duì)于Bundle過(guò)大,我們可以通過(guò)一些思路來(lái)優(yōu)化它,首先是對(duì)其嘗試進(jìn)行拆包,然后對(duì)拆包進(jìn)行約束,使公共基礎(chǔ)那部分拆成一類包,使其可以按需加載本地文件,而像業(yè)務(wù)邏輯等則拆成另一類包,使其可以按需加載線上文件.
圖片我們可以對(duì)其轉(zhuǎn)成webp格式.webp大家應(yīng)該都很熟悉了,它既支持有損壓縮又支持無(wú)損壓縮的圖片文件格式.根據(jù)官方介紹其無(wú)損壓縮后的WebP比PNG文件少了45%的文件大小,即使PNG文件經(jīng)過(guò)壓縮工具壓縮之后,WebP還可以減少28%的文件大小,這可以大大提高移動(dòng)端的圖片加載速度.據(jù)官網(wǎng)介紹在IOS平臺(tái)中,每次調(diào)整Image組件的大小,都需要重新裁剪和縮放原始圖片,重新渲染界面.這個(gè)操作開(kāi)銷會(huì)非常大,尤其是大的圖片.比起直接修改尺寸,更好的方案是使用transform:[{scale}]的樣式屬性來(lái)改變尺寸.比如當(dāng)你點(diǎn)擊一個(gè)圖片,要將它放大到全屏的時(shí)候,就可以使用這個(gè)屬性.
場(chǎng)景:某些頁(yè)面需要拜訪一個(gè)或多個(gè)業(yè)務(wù)數(shù)據(jù)服務(wù),雖然取數(shù)據(jù)是異步,但是頁(yè)面總是會(huì)有一段較長(zhǎng)的loading的時(shí)間.
優(yōu)化問(wèn)題:對(duì)于首屏所需的數(shù)據(jù)服務(wù)的訪問(wèn),使其在頁(yè)面加載階段盡早的發(fā)起數(shù)據(jù)哀求,這樣有助于減少等待數(shù)據(jù)的時(shí)間.而對(duì)長(zhǎng)時(shí)間的Loading可能會(huì)降低用戶體驗(yàn)的問(wèn)題,我們可以使用Fake頁(yè)來(lái)提高用戶體驗(yàn).先顯示一個(gè)Fake頁(yè),等數(shù)據(jù)哀求后并執(zhí)行了相應(yīng)的業(yè)務(wù)邏輯后,再替換成真正的頁(yè)面.
以上是我們?cè)趯?shí)踐中的一些優(yōu)化心得,優(yōu)化之路漫漫,吾將上下而求索.特別是在React Native還在成長(zhǎng)期這個(gè)階段,優(yōu)化變得尤為重要.期望React Native未來(lái)在性能上有更好的突破.
由InfoQ主辦的GMTC全球移動(dòng)技術(shù)大會(huì)將于6月24日在北京召開(kāi).來(lái)自BAT、攜程、滴滴、微博、和社區(qū)的技術(shù)專家聯(lián)袂分享,主題包含應(yīng)用架構(gòu)、性能優(yōu)化、動(dòng)態(tài)化、插件化、Swift、React Native、Weex等,為中高級(jí)移動(dòng)開(kāi)發(fā)工程師獻(xiàn)上一場(chǎng)技術(shù)盛宴!目前8折優(yōu)惠期間,多人團(tuán)購(gòu)更多優(yōu)惠,欲購(gòu)從速!
《React Native痛點(diǎn)解析之性能調(diào)優(yōu)》是否對(duì)您有啟發(fā),歡迎查看更多與《React Native痛點(diǎn)解析之性能調(diào)優(yōu)》相關(guān)教程,學(xué)精學(xué)透。維易PHP學(xué)院為您提供精彩教程。
轉(zhuǎn)載請(qǐng)注明本頁(yè)網(wǎng)址:
http://www.fzlkiss.com/jiaocheng/7854.html