Проблемы производительности React-Native FlatList с большим списком

Мой код получает данные Json в массив, перечисляет данные, используя FlatList. Выглядит как фото из телефонной книги и текст подряд.

Вот мой код:

  renderItem = ({ item }) => 
    (
    <ListItem
      title={item.username}
      avatar={{ uri: item.photo }}
    />
    )


  render() {
    console.log(this.state.myData);
    return (
      <View style={styles.container}>
        <FlatList
          data={this.state.myData}
          renderItem={this.renderItem}
        />
      </View>
    );
  }

Это работает, и я получаю результат, но производительность низкая. Рендеринг занимает примерно 10 секунд, что раздражает пользователя. Что я должен сделать, чтобы сделать это быстрее?


person bucsy    schedule 06.12.2017    source источник


Ответы (2)


Редактировать 20 декабря 2019: информация об этом ответе стала частью официальные документы. Вам стоит это увидеть!


Изменить от 26 мая 2018 г.: этот ответ стал более крупным и полным постом на гитхаб


Если вы следите за этой веткой, вы увидите, что команда реагирования уже знает о эта проблема с производительностью.

В этом вопросе нет серебряной пули, вы должны учитывать компромиссы каждого подхода и то, что, по вашему мнению, является хорошим опытом для вашей аудитории. Но, к счастью, есть несколько настроек, которые вы можете попробовать и улучшить свой FlatList.


Термины и значения

Используется много терминов (в документах или некоторых проблемах ), что сначала меня смутило. Итак, давайте уберем это с самого начала.

  • VirtualizedList — это компонент, лежащий в основе FlatList, и реализация React Native 'виртуальный список".

  • Производительность в этом контексте подразумевает плавную (не прерывистую) прокрутку (и навигацию по списку и обратно).

  • Потребление памяти в данном контексте – это объем информации о вашем списке, который хранится в памяти, что может привести к сбою приложения.

  • Пустые области означают, что VirtualizedList не смог отобразить ваши элементы достаточно быстро, поэтому вы вводите часть своего списка с неотображенными компонентами.

  • Окно здесь не область просмотра, а размер области, в которой должны отображаться элементы.


Реквизит

Один из способов улучшить ваш FlatList — настроить его реквизит. Вот список реквизита, который может помочь вам в этом.

removeClippedSubviews

Вы можете установить свойство removeClippedSubviews в значение true, которое размонтирует компоненты, находящиеся за пределами окна.

Win: это очень удобно для памяти, так как у вас всегда будет небольшой отображаемый список.

Компромиссы. Имейте в виду, что в этой реализации могут быть ошибки, например отсутствующий контент, если вы используете его для компонента, который не будет размонтирован (например, маршрут навигации). Он также может быть менее производительным, имея прерывистую анимацию прокрутки для больших списков со сложными элементами на не очень хороших устройствах, поскольку он выполняет сумасшедшее количество вычислений за прокрутку.

максторендерпербатч

Вы можете установить maxToRenderPerBatch={number}, который является реквизитом VirtualizedList, который можно передать непосредственно в FlatList. При этом вы можете контролировать количество элементов, отображаемых в пакете, то есть следующий фрагмент элементов, отображаемых при каждом прокрутке.

Победа. Установка большего числа означает меньше видимых пустых областей при прокрутке (лучше скорость заполнения).

Компромисс: большее количество элементов в пакете означает меньшую производительность JavaScript, что означает меньшую скорость отклика (нажатие элемента и открытие сведений). Если у вас есть статический и неинтерактивный список, это может быть выходом.

InitialNumToRender

Вы можете установить initialNumToRender={number}. Это означает начальное количество элементов для рендеринга.

Победа. Вы можете установить это значение на точное количество элементов, которые будут покрывать экран для каждого устройства. Это может значительно повысить производительность при рендеринге компонента списка.

Компромисс: вы, скорее всего, увидите пустые области при установке низкого initialNumToRender.

размер окна

Вы можете установить windowSize={number}. Передаваемое здесь число является единицей измерения, где 1 эквивалентно высоте вашего окна просмотра. Значение по умолчанию — 21, то есть 10 окон просмотра вверху, 10 внизу и один между ними.

Победа. Если вы в основном беспокоитесь о производительности, вы можете установить большее значение windowSize, чтобы ваш список работал плавно и с меньшим количеством пробелов. Если вы в основном беспокоитесь о потреблении памяти, вы можете установить более низкое значение windowSize, чтобы ваш отображаемый список был меньше.

Компромисс: чем больше windowSize, тем больше потребление памяти. Для более низкого windowSize у вас будет более низкая производительность и большее изменение видимости пустых областей.

НаследиеРеализация

Это свойство, когда оно равно true, заставит ваш FlatList полагаться на более старый ListView вместо VirtualizedList.

Победа. Это определенно повысит производительность вашего списка, поскольку он удаляет виртуализацию и отображает все ваши элементы одновременно.

Компромисс. Потребление памяти резко возрастает, и велика вероятность, что большой список (более 100 элементов) со сложными элементами приведет к сбою вашего приложения. Он также выдает предупреждение о том, что вышеуказанные настройки не будут работать, потому что вы теперь находитесь в ListView.

отключить виртуализацию

Вы увидите, как люди выступают за использование этой опоры по некоторым вопросам. Но теперь это устарело. Раньше это делало что-то похожее на legacyImplementation.


Элементы списка

Есть также несколько беспроигрышных стратегий, которые включают компоненты вашего списка. Они часто управляются VirtualizedList, поэтому они должны быть быстрыми.

Используйте простые компоненты

Чем сложнее ваши компоненты, тем медленнее они будут отображаться. Старайтесь избегать большого количества логики и вложенности в элементы списка. Если вы часто повторно используете этот компонент элемента списка в своем приложении, создайте дубликат только для ваших больших списков и сделайте их как можно менее логичными и менее вложенными.

Используйте легкие компоненты

Чем тяжелее ваши компоненты, тем медленнее они рендерятся. Избегайте тяжелых изображений (используйте обрезанную версию для элементов списка, как можно меньше). Поговорите со своей командой дизайнеров, используйте в своем списке как можно меньше эффектов, взаимодействий и информации. Сохраните их в деталях вашего товара.

Использовать следуетобновление компонента

Реализуйте проверку обновлений для своих компонентов. PureComponent в React в основном нужен, когда у вас нет времени на размышления. Если вы читаете это, значит, у вас есть время, поэтому создайте самые строгие правила для компонентов вашего списка. Если ваш список достаточно прост, вы можете даже использовать

shouldComponentUpdate() {
  return false
}
person Filipe Merker    schedule 25.05.2018
comment
По большей части это выглядит как копия реактивной документации по оптимизации конфигурации FlatList. Я думаю, вы должны были связать исходную документацию facebook.github.io/ реакция-родной/документы/ - person Tyler; 13.12.2019
comment
@Tyler Если вы копнете глубже, вы увидите, что этот раздел документации PR на основе моей статьи. Так что этот пост прямо здесь является источником всего этого. - person Filipe Merker; 18.12.2019
comment
Вы ищете реквизит или что-то в этом роде? С какой стати мне копаться глубже в PR документации? Я просто предлагаю, чтобы этот ответ ссылался на документацию, которая содержит больше информации, чем этот ответ, и, скорее всего, останется более актуальной. - person Tyler; 21.12.2019
comment
Это полезная информация, но у меня есть вопрос: сколько это слишком много? Я поэкспериментировал с параметрами и выяснил, что в моем случае (каждый элемент списка имеет ползунок с 2 изображениями и текстом) windowSize=30 и maxToRenderPerBatch=60 дают плавную прокрутку. Но я беспокоюсь, если эти цифры слишком велики - person Gennady Dogaev; 18.06.2020
comment
@GennadyDogaev это действительно индивидуальный случай. Для меня это выглядит нормально. Размер окна по умолчанию равен даже 21. Максимальный рендеринг на пакет немного высок (вы в основном визуализируете все элементы при каждой прокрутке), но если это работает, все в порядке. Я думаю, что вы круты с этой конфигурацией! - person Filipe Merker; 18.06.2020

Вот некоторые улучшения, которые вы можете сделать, чтобы оптимизировать свой плоский список:

  1. Pagination
    • You can paginate your data in your backend and refetch it when your scroll gets closer to the end. onEndReached and onEndReachedThreshold can help you.
  2. Update your React Native version to 49 or latest
    • Fiber 16 has amazing performance improvement which makes everything runs faster and smoother
  3. Use PureComponent for render item
    • PureComponent improves the rendering and memory usage of your component, creating render items as pure gives you a better performance experience
  4. Define getItemLayout prop
    • It improves item rendering since React will previously know its layout definition

Надеюсь, поможет

person soutot    schedule 06.12.2017