iOS 10 Pre-Fetching研究
Boost Smooth Scrolling with iOS 10 Pre-Fetching API
一句話解釋Pre-Fetching
- 就是提早load,延後release。
滾動遲鈍的原因
簡單來說,就是app drop frames,所以使用者會感受到遲鈍。
- 60 FPS (Frames Per Second),也就是每個frame只有16ms (1000ms/60frames ~ 16ms/frame)的時間來進行畫面的呈現。
- 當某個畫面的呈現的時間大於16ms,系統就會drop這個畫面,這也是使用者會感受到遲鈍的原因。
常發生的場景。
- 從網路下載圖片。
- 從資料褲讀取資料。
Cell在iOS9下的life cycle
Cell會依序呼叫下列這些方法
- collectionView(_:cellForItemAt:)
- collectionView(_:willDisplay:forItemAt:)
- collectionView(didEndDisplaying:forItemAt:)
Cell在iOS10下的life cycle
life cycle跟iOS9其實還是一樣,但有下列幾點改變了。
- collectionView(_:cellForItemAt:),跟iOS9相比,會更早被呼叫,讓loading重的cell有機會提早進行準備。
collectionView(didEndDisplaying:forItemAt:,即使執行到這個method,cell不會馬上被系統回收,以防使用者如果改變滑動方向,也不需要重新loading這個cell。
同一列的多個cell不是被同時loading到畫面上,而是依序被laoding到畫面中,進行減少cpu的使用量,也降低每個frame的呈現時間。
Pre-Fetching API
- 會根據使用者的滑動速度,來調整預先加載的cell個數。
- 滑動速度越快,可能預先加載的cell個數越多。
在沒有這個Pre-Fetching API,如果想優化整個scorll的速度時,應該要把cell的content的加載分散到各個method(willDisplay:forItemAt,didEndDisplaying:forItemAt)中,減少cellForItemAt的loading。
- 注意: 有了Pre-Fetching,所以當cellForItemAt被執行時,並不代表這個cell真的出現在這個畫面上。
- Prefetching預設是打開的,可以透過isPrefetchingEnabled關閉。
Pre-Fetching API and UICollectionView
通常pre-fetch的預先加載cell個數是由系統自動決定。但也可以由程式來決定,透過實作UICollectionViewDataSourcePrefetching protocol。
- collectionView(_:prefetchItemsAt:) (required)
- 可透過indexPath來指定多少cell需要預先被進行加載。
- 此加載是非同步的,來減少main queue的loading。
- collectionView(_:cancelPrefetchingForItemsAt:) (optional)
pre-fetch其實是相當黑箱的,即使在程式中時做了collectionView(:prefetchItemsAt:),並不保證每一個cell都會執行到這個method,所以在collectionView(:cellForItemAt:)還是要確保可以處理所有cell畫面的呈現。