React Native性能優化:預載入和緩存View

開發App時,View跳轉的平滑度是一個很重要的性能指標,也是區分WebApp和原生App的關鍵點。無論原生app還是WebApp,在跳轉過程通常涉及以下幾個流程。

1.原View出發動作,UI線程開始執行對應的handle。

2.在handle上獲取下個View的數據 (如果數據在後端,還需要遠程非同步獲取)

3.將數據傳給下一個View進行渲染(對於web,view很有可能需要遠程獲取)

4.UI線程結束handle的處理,底層框架開始做渲染樹的樣式,layout計算,paint直到將最後的frame輸出到顯卡。

5.底層框架開發觸發動畫,講新生產的view平滑的移到用戶面前。

前端的性能指標其實很簡單,就是60fps。無論web,app,還是遊戲都是一樣的要求。因此新的frame最好要在16ms內完成,否則很容易出現卡頓感覺,比如在view跳轉動畫時。但假設原界面和新界面之前的切換不需要動畫,即使達不到60fps,視覺上可能都不會有很大的卡頓感覺。

像數據和view都在遠端的情況,實際上不可能在16ms內完成下一個frame的渲染。因此必須在設計上引入loading的機制,在跳轉的時候render一個相對簡單的loading界面,等數據和view都ready的時候,再刷新界面,這個時候由於沒有動畫,所以不太會有明顯卡頓感,除非新界面渲染很複雜。

接下來要講,當下一個view和需要data在跳轉前都在本地並且交互上不允許採用loading的設計,出現卡頓感怎麼辦處理。比如我們做IM的時候,從會話列表進入聊天窗口,經常會有點卡頓感覺,因為聊天對話界面的結構相對比較複雜。如果每次進去都需要重新構建渲染,肯定無法在16ms內完成。解決方法就是準備一個聊天對話界面的樣板,在app啟動的時候將它預先載入。當需要渲染的時候,只需要將修改對應的值就可以,退去時不要去銷毀它,直接cache下來留給下次使用。

具體在react native上怎麼實現,這需要定製自己的navigator,因為react native提供的navigator沒有這種功能。具體原理就是在navigator的render函數里一直保留需要預先載入和緩存的view,當不需要顯示的時候將它隱藏起來。同時需要緩衝的view一定要有初始樣板。

//navigator<MYNavigator {... this.props} routeState={routes} preLoad={[b]} routesMap={{ "a":<A></A>, "b":<B></B>, "c":<C></C> }}/>//navigator組件的render方法_renderSense(){ var res=this.state.senses.map(((senseKey)=>{ const SenseView =this.props.routesMap[senseKey.key].type return ( <Card key={senseKey.key} curSense={senseKey.key} index={this.state.index} {... this.props} > <SenseView dispatch={this.props.dispatch}> </SenseView> </Card> ); }).bind(this)) //預先載入和cache var preLoad=this._renderPreLoadFunc() return res.concat(preLoad);}//預先載入的樣板的reducerinitData=Array(100).fill(-1).map((item,index)=>this.tick+:+index);export default function routes(state = initData, action) { switch (action.type) { case "UPDATE" :{ return [...action.data] } default: return state }}

推薦閱讀:

輕鬆遷移博客到AMP
2018 前端性能優化清單 —— 第一部分
PWA 漸進式實踐 (2) - Service Worker
一道滴滴的負載均衡前端面試題
網頁圖片載入優化方案

TAG:ReactNative | React | 前端性能优化 |