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