簡體   English   中英

React Native - VirtualizedList:您有一個更新緩慢的大列表

[英]React Native - VirtualizedList: You have a large list that is slow to update

介紹

我的 VirtualizedList(無限滾動)遇到了嚴重的性能問題......我一直在關注 這個以改進它,但仍然工作很慢。

當我向下滾動時,UI 線程從 60fps 到 30fps,JS 線程從 60fps 到 10/20fps(有時到 0fps)。 在 iOS (iPhone 6) 上它似乎比在我的 Android (Samsung Galaxy S8+) 上流暢

我的 VirtualizedList 正在渲染具有不同高度的項目,並在到達終點時獲取數據。 我的項目從 React.PureComponent 擴展,因為它是推薦的:

VirtualizedList:您有一個更新緩慢的大列表 - 確保您的 renderItem 函數呈現遵循 React 性能最佳實踐的組件,如 PureComponent、shouldComponentUpdate 等。 Object { "contentLength": 20720, "dt": 532, "prevDt" : 2933, }

當我向下滾動大約 20 個項目時會出現這個問題......

代碼

這是 VirtualizedList 的代碼:

const keyExtractor = ({ id }) => id;
...
 
getItem = (data, index) => data[index];

getItemCount = (data) => data.length;

renderItem = ({ item, index }) => {
 const {
   images,
   dimensions,
   description,
   location,
   likes,
   comments,
   date,
 } = item;

 return (
   <Card
     images={images}
     postDimensions={dimensions}
     description={description}
     location={location}
     likes={likes}
     comments={comments}
     date={date}
   />
 );
};

<VirtualizedList
    data={data}
    getItem={this.getItem}
    getItemCount={this.getItemCount}
    keyExtractor={keyExtractor}
    listKey={listKey}
    legacyImplementation={false}
    numColumns={1}
    renderItem={this.renderItem}
    initialNumToRender={MAX_POSTS_TO_RETRIEVE_LENGTH} // 10
    windowSize={32}
    maxToRenderPerBatch={15}
    updateCellsBatchingPeriod={50}
    removeClippedSubviews={false}
    ListFooterComponent={this.renderFooter}
    ListEmptyComponent={ListEmptyComponent}
    onEndReached={onEndReached}
    onEndReachedThreshold={0.5}
/>

Pd:我渲染的每個項目都有一個唯一的 ID。

我試過的

我試圖為 List 實現我自己的 getItemLayout 方法,但由於某種原因它不能正常工作。

警告:失敗的框架類型:框架frame.lengthVirtualizedList.getItemLayout被標記為 required ,但其值為undefined

itemHeights = [];

getItemLayout = (data, index) => {
  const length = this.itemHeights[index];
  const offset = this.itemHeights.slice(0,index).reduce((a, c) => a + c, 0)
  return {length, offset, index}
}

renderItem = ({ item, index }) => {
 const {
   images,
   dimensions,
   description,
   location,
   likes,
   comments,
   date,
 } = item;

 return (
   <View onLayout={(event) => this.itemHeights[index] = event.nativeEvent.layout.height}>
    <Card
      images={images}
      postDimensions={dimensions}
      description={description}
      location={location}
      likes={likes}
      comments={comments}
      date={date}
    />
   </View>
 );
};

<VirtualizedList
    data={data}
    getItem={this.getItem}
    getItemCount={this.getItemCount}
    getItemLayout={this.getItemLayout}
    keyExtractor={keyExtractor}
    listKey={listKey}
    legacyImplementation={false}
    numColumns={1}
    renderItem={this.renderItem}
    initialNumToRender={MAX_POSTS_TO_RETRIEVE_LENGTH} // 10
    windowSize={32}
    maxToRenderPerBatch={15}
    updateCellsBatchingPeriod={50}
    removeClippedSubviews={false}
    ListFooterComponent={this.renderFooter}
    ListEmptyComponent={ListEmptyComponent}
    onEndReached={onEndReached}
    onEndReachedThreshold={0.5}
/>

有任何想法嗎? 我已經看到這是一個常見問題,但我還沒有找到任何解決方案。

更新

要解決我使用 getItemLayout 遇到的問題,請執行以下操作:

getItemLayout = (data, index) => {
  const length = this.itemHeights[index] || 0; // <----- if undefined return 0
  const offset = this.itemHeights.slice(0,index).reduce((a, c) => a + c, 0)
  return {length, offset, index}
}

如果有人遇到這種情況,請使用我的自定義 getItemLayout 函數並按照以下步驟操作

使用這些價值觀對我有用。

    initialNumToRender={10}
    windowSize={5}
    maxToRenderPerBatch={5}
    updateCellsBatchingPeriod={30}
    removeClippedSubviews={false}
    ...
    onEndReachedThreshold={0.1}

Pd:我的視口被 1.5 個項目覆蓋

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM