VirtualizedList

React 17.0.2

React-native 0.67.3

VirtualizedList

VirtualizedList

<VirtualizedList
data={[{key: 'i1'}, {key: 'i2'}, {key: 'i3'}]}
renderItem={({item}) => <item value={item.key} />}
getItem={(data, index) => data[index]}
getItemCount={data => data.length}
/>

maxToRenderPerBatch,每次渲染的个数

初始化

  • FillRateHelper 初始化
  • Batchinator初始化
  • initialState的first和last赋值,first为initialScrollIndex(默认0),last为first+initialNumToRender

windowSize

默认21。1相当于一个可视窗口,数字大时看到白屏的几率少,数字小时内存占用少

initialNumToRender,首次渲染个数,默认10个。指定一开始渲染的元素数量,最好刚刚够填满一个屏幕,这样保证了用最短的时间给用户呈现可见的内容。注意这第一批次渲染的元素不会在滑动过程中被卸载,这样是为了保证用户执行返回顶部的操作时,不需要重新渲染首批元素。

先介绍_pushCells作用,这里会把first到last(参数)的CellRenderer push进去

render

  • 调用_pushCells,first为0,last为initialNumToRender(默认10)
  • 接着再调用_pushCells,first为firstAfterInitial(Math.max(lastInitialIndex + 1, first)),其中lastInitialIndex为initialNumToRender,last则为全局变量last(初始为initialNumToRender,后为state.last+maxToRenderPerBatch)
  • 假设isVirtualizationDisabled没有禁用,并且last小于item个数,cells会在尾部push一个view
  • 如果last小于item个数,_hasMore赋值为true
  • 最后调用innerRet,返回一个ScrollView,体现为_scrollRef

_maybeCallOnEndReached,如果last为数据源最后一个,调用onEndReached

_maybeCallOnEndReached的Caller

  • _onLayout
  • _onContentSizeChange
  • _onScroll

_scheduleCellsToRenderUpdate

  • 这里会进行高优先级判断,如果接近最后一项则标记为高优先级
  • 若高优先级,则直接调用_updateCellsToRender渲染,若非高优先级则this._updateCellsToRenderBatcher.schedule()进行调度渲染

_scheduleCellsToRenderUpdate的Caller

  • componentDidUpdate
  • _onCellLayout
  • _onLayout
  • _onContentSizeChange
  • _onScroll

_onScroll

  • _updateViewableItems,这里会调用ViewabilityHelper的onUpdate方法,这里会找出哪些item是可见的,并且调用onViewableItemsChanged,通知可见项目发生了改变
  • _maybeCallOnEndReached
  • _scheduleCellsToRenderUpdate
    • 如果是高优先级任务,先调用_updateCellsToRenderBatcher的dispose方法,然后调用_updateCellsToRender
    • 如果是低优先级任务,调用_updateCellsToRenderBatcher的schedule,这里是异步执行callback,callback的内容是调用_updateCellsToRender方法

_updateCellsToRender

  • _updateViewableItems
  • 调用setState进行更新

CellRenderer

CellRenderer

  • 一个普通View/CellRendererComponent(外部传入)作为容器
  • 里面的element由外部传入,通过React.createElement生成
  • 最终通过VirtualizedListCellContextProvider 返回

FlatList

官方示例

class MyListItem extends React.PureComponent {
  _onPress = () => {
    this.props.onPressItem(this.props.id);
  };

  render() {
    const textColor = this.props.selected ? "red" : "black";
    return (
      <TouchableOpacity onPress={this._onPress}>
        <View>
          <Text style={{ color: textColor }}>
            {this.props.title}
          </Text>
        </View>
      </TouchableOpacity>
    );
  }
}

class MultiSelectList extends React.PureComponent {
  state = {selected: (new Map(): Map<string, boolean>)};

  _keyExtractor = (item, index) => item.id;

  _onPressItem = (id: string) => {
    // updater functions are preferred for transactional updates
    this.setState((state) => {
      // copy the map rather than modifying state.
      const selected = new Map(state.selected);
      selected.set(id, !selected.get(id)); // toggle
      return {selected};
    });
  };

  _renderItem = ({item}) => (
    <MyListItem
      id={item.id}
      onPressItem={this._onPressItem}
      selected={!!this.state.selected.get(item.id)}
      title={item.title}
    />
  );

  render() {
    return (
      <FlatList
        data={this.props.data}
        extraData={this.state}
        keyExtractor={this._keyExtractor}
        renderItem={this._renderItem}
      />
    );
  }
}

render函数的实现

外层为VirtualizedList

内层调用_renderer函数,返回renderItem

  • 若列数不大于1则直接调用renderer函数,renderer函数内返回调用renderItem
  • 若列数大于1,则返回一个View,View内遍历item(Array类型),返回Fragment,Fragment内会调用renderer函数

renderer函数内,如果设置了ListItemComponent,则返回ListItemComponent,否则返回renderItem函数调用

results matching ""

    No results matching ""