ScrollView
API
ScrollView是其中最簡單的一個組件,它只是以列表的方式來顯示子組件,并且只會render一次。對于很多應用場景而言這是不好的,當我需要渲染的數據data特別大,比如5000條數據的時候,我需要等待許久才能看到ScrollView中的東西,并且在我想要進行滑動的時候會感受到明顯的卡頓。嚴重的時候android會ANR。
所以這一特點使得ScrollView一般只有在渲染數據量少的情況下才會使用。
應用場景:幻燈片,部分GridView,廣告列表欄...
但有個場景ScrollView非常合適,當item中有很復雜的繪制,比如說有一個View的數組,那使用
ScrollView在滑動的時候就不會出現VIew數組重新render的情況,避免一些意想不到的UI問題
ListView
API
這個組件的設計思路和ScrollView完全不同,ListView基于一個數據源,對數據源中的每一項數據調用renderRow進行render。并且不會一次性render所有數據,而是首先render屏幕上能看到的數據(假實現)。這樣對于內存消耗和當數據量過大時避免卡頓有所幫助。基于這種設計,我們可以在renderRow中使用rowData為數據源再嵌套一個子ListView
應用場景:數據量多的list
缺點
1.該組件對于render數據的優化并不完全,一般而言,當數據量超過500+后且已經滑動到500+行,繼續滑動屏幕會有明顯卡頓,這是因為ListView的內部實現還是ScrollView,react-native的Listview確實就是在scrollView里面不斷添加row,但row移出可見范圍之外后依然還在scrollview里面,不像安卓和ios的在移出視野之外后可以繼續被后面出來的row復用。。
2.需要繪制分隔線的時候,第一個元素的上面不會繪制分隔線。
3.當數據結構比較復雜的時候,比如[{"key":[{},{}...]}, {}...]的時候,默認的section解析方式就不能正確解析出你需要的數據,需要自己去定義getRowData()和getSectionHeader()來解析數據。
有SectionHeader的默認數據結構:
4.性能問題參考鏈接:
ListView renders all rows?
ListView 性能問題
5.因為FlatList的出世,ListView基本上就是過去式了。
FlatList
API
核心原理 : 用戶看不到的 items,就用空白代替,這樣既節約內存,渲染又快。缺點就是,用戶可能滾動太快,空白還沒被渲染成真的 items,就被看見了。
在官方api中首先強調的就是這是一個高性能的組件。FlatList應該是實現了 真 ·只 render所見內容。因為FlatList是基于 <VirtualizedList>組件進行的封裝。所以有下面的問題需要注意
- 當某行滑出渲染區域之外后,其內部狀態將不會保留。請確保你在行組件以外的地方保留了數據。
- 為了優化內存占用同時保持滑動的流暢,列表內容會在屏幕外異步繪制。這意味著如果用戶滑動的速度超過渲染的速度,則會先看到空白的內容。這是為了優化不得不作出的妥協,而我們也在設法持續改進。
- 本組件繼承自PureComponent而非通常的Component,這意味著如果其props在淺比較中是相等的,則不會重新渲染。所以請先檢查你的renderItem函數所依賴的props數據(包括data
屬性以及可能用到的父組件的state),如果是一個引用類型(Object或者數組都是引用類型),則需要先修改其引用地址(比如先復制到一個新的Object或者數組中),然后再修改其值,否則界面很可能不會刷新。 - 默認情況下每行都需要提供一個不重復的key屬性。也可以提供一個keyExtractor函數來生成key。
由于上述Flatist做出的優化而會導致一個問題,如果在每個Item中有個從網絡拿的Image,那么在list很長的情況下,底部的部分數據的Image可能永遠都無法顯示。
注意 : 這里可以看到FlatList特性的解釋和一個官方的例子 FlatList Features & Example
為什么使用FlatList而非ListView
首先是在大數據量的情況下,FlatList性能更好。其次,ListView和FlatList的使用方式基本一致,ListView很容易轉換為FlatList。最后,FlatList對于app而言具有良好的擴展性