React Native中RecyclerListView如何高效实现长列表滚动与优化?

2026-04-02 07:191阅读0评论SEO资源
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计2698个文字,预计阅读时间需要11分钟。

React Native中RecyclerListView如何高效实现长列表滚动与优化?

目录 + RecyclerListView 的介绍与使用

1.安装

2.概述和功能

3.RecyclerListView 的使用

React Native中RecyclerListView如何高效实现长列表滚动与优化?

1. dataProvider 2. LayoutProvider 3. rowRenderer 4. onEndReached 5. onEndReachedThreshold 6. extendedState 7. scrollViewProps

目录
  • recyclerlistview的介绍与使用
    • 1.安装
    • 2.概述和功能
    • 3. RecyclerListView的使用
      • 1、dataProvider
      • 2、LayoutProvider
      • 3、rowRenderer
      • 4、onEndReached
      • 5、onEndReachedThreshold
      • 6、extendedState
      • 7、scrollViewProps
  • RecyclerListView所有属性

    recyclerlistview的介绍与使用

    1.安装

    npm install --save recyclerlistview 或者: yarn add recyclerlistview

    2.概述和功能

    RecyclerListView 是一个高性能的列表(listview)组件,同时支持 React NativeWeb ,并且可用于复杂的列表。RecyclerListView 组件的实现灵感,来自于 Android RecyclerView原生组件及iOS UICollectionView原生组件。

    RecyclerListView使用“cell recycling”来重用不再可见的视图来呈现项目,而不是创建新的视图对象。 对象的创建非常昂贵并且带有内存开销,这意味着当您滚动列表时内存占用量不断增加。 从内存中释放不可见的项目是另一种技术,但这会导致创建更多的对象和大量的垃圾收集。 回收是渲染无限列表的最佳方式,不会影响性能或内存效率。

    为什么需要RecyclerListView

    我们知道,React Native 的其他列表组件如ListView,会一次性创建所有的列表单元格——cell。如果列表数据比较多,则会创建很多的视图对象,而视图对象是非常消耗内存的。所以,ListView组件,对于我们业务中的这种无限列表,基本上是不可以用的。

    对于React Native 官方提供的高性能的列表组件FlatList, 在Android设备上的表现,并不是十分友好。它的实现原理,是将列表中不在可视区域内的视图,进行回收,然后根据页面的滚动,不断的渲染出现在可视区域内的视图。这里需要注意的是,FlatList是将不可见的视图回收,从内存中清除了,下次需要的时候,再重新创建。这就要求设备在滚动的时候,能快速的创建出需要的视图,才能让列表流畅的展现在用户面前。而问题也就出现在这里,Android设备因为老化等原因,计算力等跟不上,加之React Native 本身 JS 层与 Native 层之间交互的一些问题(这里不做深入追究),导致创建视图的速度达不到使列表流畅滚动的要求。

    那怎样来解决这样的问题呢?

    RecyclerListView 受到 Android RecyclerViewiOS UICollectionView 的启发,进行两方面的优化:

    • 仅创建可见区域的视图,这步与FlatList是一致的。
    • cell recycling,重用单元格,这个做法是FlatList缺乏的。

    对于程序来说,视图对象的创建是非常昂贵的,并且伴随着内存的消耗。意味着如果不断的创建视图,在列表滚动的过程中,内存占用量会不断增加。FlatList中将不可见的视图从内存中移除,这是一个比较好的优化手段,但同时也会导致大量的视图重新创建以及垃圾回收。

    RecyclerListView 通过对不可见视图对象进行缓存及重复利用,一方面不会创建大量的视图对象,另一方面也不需要频繁的创建视图对象和垃圾回收。

    基于这样的理论,所以RecyclerListView的性能是会优于FlatList的。

    3. RecyclerListView的使用

    属性:

    1、dataProvider

    首先需要定义一个数据驱动方法

    let dataProvider = new DataProvider((r1, r2) => { return r1 !== r2; })

    定义完成之后去初始化数据

    // 列表数据 const [JRecyclerData, setJRecyclerData] = useState(_dataProvider.cloneWithRows(data));

    cloneWithRows

    • 想要更新列表的dataProvider数据也就是(DataSource)必须每次通过cloneWithRows这个来重新挂载datasource的值。
    • clone方法会自动提取新数据并进行逐行对比(使用rowHasChanged方法中的策略),这样列表就知道哪些行需要重新渲染了。

    2、LayoutProvider

    定义列表布局

    在这之前我们可以根据我们的业务场景,规划处几类的布局,然后自定义每种布局的类型来区分。

    //表示列表中会出现三种ui类型的item const ViewTypes = { FULL: 0, HALF_LEFT: 1, HALF_RIGHT: 2 }

    下面就可以来区分布局了

    • 为了进行cell-recycling,RecyclerListView要求对每个cell(通常也叫Item)定义一个type,根据type设置cell的dim.widthdim.height

    //第一个函数是定义item的ui类型,第二个是定义item的高宽 this._layoutProvider = new LayoutProvider( index => { if (index % 3 === 0) { return ViewTypes.FULL; } ... }, (type, dim) => { switch (type) { case ViewTypes.HALF_LEFT: dim.width = width / 2; dim.height = 160; break; ... } } )

    3、rowRenderer

    rowRenderer负责渲染一个cell,同样是根据type来进行渲染:

    _rowRenderer(type, data) { switch (type) { case ViewTypes.HALF_LEFT: return ( <CellContainer style={styles.containerGridLeft}> <Text>Data: {data}</Text> </CellContainer> ); ... } }

    例子:

    /*** * To test out just copy this component and render in you root component */ export default class RecycleTestComponent extends React.Component { constructor(args) { super(args); let { width } = Dimensions.get("window"); //Create the data provider and provide method which takes in two rows of data and return if those two are different or not. let dataProvider = new DataProvider((r1, r2) => { return r1 !== r2; }); //Create the layout provider //First method: Given an index return the type of item e.g ListItemType1, ListItemType2 in case you have variety of items in your list/grid //Second: Given a type and object set the height and width for that type on given object //If you need data based check you can access your data provider here //You'll need data in most cases, we don't provide it by default to enable things like data virtualization in the future //NOTE: For complex lists LayoutProvider will also be complex it would then make sense to move it to a different file this._layoutProvider = new LayoutProvider( index => { if (index % 3 === 0) { return ViewTypes.FULL; } else if (index % 3 === 1) { return ViewTypes.HALF_LEFT; } else { return ViewTypes.HALF_RIGHT; } }, (type, dim) => { switch (type) { case ViewTypes.HALF_LEFT: dim.width = width / 2 - 0.0001; dim.height = 160; break; case ViewTypes.HALF_RIGHT: dim.width = width / 2; dim.height = 160; break; case ViewTypes.FULL: dim.width = width; dim.height = 140; break; default: dim.width = 0; dim.height = 0; } } ); this._rowRenderer = this._rowRenderer.bind(this); //Since component should always render once data has changed, make data provider part of the state this.state = { dataProvider: dataProvider.cloneWithRows(this._generateArray(300)) }; } _generateArray(n) { let arr = new Array(n); for (let i = 0; i < n; i++) { arr[i] = i; } return arr; } //Given type and data return the view component _rowRenderer(type, data) { //You can return any view here, CellContainer has no special significance switch (type) { case ViewTypes.HALF_LEFT: return ( <CellContainer style={styles.containerGridLeft}> <Text>Data: {data}</Text> </CellContainer> ); case ViewTypes.HALF_RIGHT: return ( <CellContainer style={styles.containerGridRight}> <Text>Data: {data}</Text> </CellContainer> ); case ViewTypes.FULL: return ( <CellContainer style={styles.container}> <Text>Data: {data}</Text> </CellContainer> ); default: return null; } } render() { return <RecyclerListView layoutProvider={this._layoutProvider} dataProvider={this.state.dataProvider} rowRenderer={this._rowRenderer} />; } } const styles = { container: { justifyContent: "space-around", alignItems: "center", flex: 1, backgroundColor: "#00a1f1" }, containerGridLeft: { justifyContent: "space-around", alignItems: "center", flex: 1, backgroundColor: "#ffbb00" }, containerGridRight: { justifyContent: "space-around", alignItems: "center", flex: 1, backgroundColor: "#7cbb00" } };

    页面效果:

    但是在实际的业务开发中肯定不会是这么简单的,一般都会用到分页,下拉刷新什么的,下面介绍几个比较常用的属性:

    4、onEndReached

    列表触底是触发,一般是用来做上拉加载更过数据的时候来使用的

    <RecyclerListView layoutProvider={this._layoutProvider} dataProvider={this.dataProvider.cloneWithRows(this.state.infoList)} rowRenderer={this._rowRenderer} onEndReached={this._onLoadMore} />

    5、onEndReachedThreshold

    列表距离底部多大距离时触发onEndReached的回调,这个填写的是具体的像素值,与FlatList是有区别的,FlatList填写的是百分比

    <RecyclerListView layoutProvider={this._layoutProvider} dataProvider={this.dataProvider.cloneWithRows(this.state.infoList)} rowRenderer={this._rowRenderer} onEndReached={this._onLoadMore} onEndReachedThreshold={50} />

    6、extendedState

    在更新目前列表渲染以外的数据时,可以使用此属性更新状态,以便绘制出新的列表,并且不再重新渲染以前的列表数据

    <RecyclerListView layoutProvider={this._layoutProvider} dataProvider={this.dataProvider.cloneWithRows(this.state.infoList)} rowRenderer={this._rowRenderer} onEndReached={this._onLoadMore} onEndReachedThreshold={50} extendedState={this.state} />

    7、scrollViewProps

    继承scrollView的属性,RecyclerListView本身是不具有刷新属性的,要想使用刷新功能,就可以继承scrollView的下拉刷新

    <RecyclerListView scrollViewProps={{ refreshControl: ( <RefreshControl refreshing={this.state.loading} onRefresh={async () => { this.setState({ loading: true }); await this.getInfo(); this.setState({ loading: false }); }} /> ) }} />

    下面看一下完整的例子:

    import React, { Component } from "react"; import { View, Text, Dimensions, StyleSheet, RefreshControl, Alert } from "react-native"; import { RecyclerListView, DataProvider, LayoutProvider } from "recyclerlistview"; import WBCST from "./../../rn-app"; const ViewTypes = { FULL: 0 }; const { width } = Dimensions.get("window"); const styles = StyleSheet.create({ container: { flexDirection: "row", justifyContent: "space-between", // alignItems: "center", flex: 1, backgroundColor: "#fff", // borderWidth: 1, borderColor: "#dddddd", margin: 15, marginTop: 0, padding: 15 }, topicLeft: { width: width - 210, marginRight: 10 }, topicRight: { backgroundColor: "#f5f5f5", width: 140, height: 140, padding: 15 }, topicTitle: { color: "#000", fontSize: 16, fontWeight: "700", lineHeight: 28 }, topicContext: { color: "#999", fontSize: 12, lineHeight: 18, marginTop: 10 }, topicNum: { fontSize: 14, marginTop: 20 }, topicRightText: { fontSize: 14, color: "#666" } }); export default class RecycleTestComponent extends Component { constructor(props) { super(props); this.dataProvider = new DataProvider((r1, r2) => { return r1 !== r2; }); let { width } = Dimensions.get("window"); this._layoutProvider = new LayoutProvider( (index) => { return ViewTypes.FULL; }, (type, dim) => { dim.width = width; dim.height = 190; } ); this.state = { pagenum: 1, infoList: [], loading: false, isLoadMore: false }; } getInfo = () => { let num = this.state.pagenum; let info = this.state.infoList; WBCST.getFetch("app.58.com/api/community/aggregatepage/tabs/topic", { pagesize: 20, pagenum: num }).then((res) => { if (res) { let loadMore = false; if (num == 1) { if (res.data.questions.length == 20) { loadMore = true; } this.setState({ isLoadMore: loadMore, infoList: res.data.questions }); } else { // info.concat(res.data.questions); if (res.data.questions.length < 20) { loadMore = false; } else { loadMore = true; } this.setState({ isLoadMore: loadMore, infoList: this.state.infoList.concat(res.data.questions) }); } } }); }; _rowRenderer = (type, data) => { return ( <View style={styles.container}> <View style={styles.topicLeft}> <Text numberOfLines={2} style={styles.topicTitle}> {data.topic.title} </Text> <Text numberOfLines={2} style={styles.topicContext}> {data.topic.context} </Text> <Text style={styles.topicNum}> {data.topic.pn} 人参与此话题 </Text> </View> <View style={styles.topicRight}> <Text style={styles.topicRightText}>{data.user.name}</Text> <Text style={[{ marginTop: 10 }, styles.topicRightText]}>{data.title}</Text> </View> </View> ); }; _renderFooter = () => { return ( <View> <Text>上拉加载更多</Text> </View> ); }; _onLoadMore = () => { // Alert.alert(JSON.stringify("num")); if (!this.state.isLoadMore) { return; } let num = this.state.pagenum; num = num + 1; this.setState( { pagenum: num }, () => { // Alert.alert(JSON.stringify(num)); this.getInfo(); } ); }; componentDidMount = () => { this.getInfo(); }; render() { return ( <RecyclerListView layoutProvider={this._layoutProvider} dataProvider={this.dataProvider.cloneWithRows(this.state.infoList)} rowRenderer={this._rowRenderer} extendedState={this.state} onEndReached={this._onLoadMore} onEndReachedThreshold={50} // renderFooter={this._renderFooter} scrollViewProps={{ refreshControl: ( <RefreshControl refreshing={this.state.loading} onRefresh={async () => { this.setState({ loading: true }); // analytics.logEvent("Event_Stagg_pull_to_refresh"); await this.getInfo(); this.setState({ loading: false }); }} /> ) }} /> ); } }

    效果图:

    RecyclerListView所有属性

    以上就是ReactNative系列之Recyclerlistview使用详解的详细内容,更多关于ReactNative使用Recyclerlistview的资料请关注易盾网络其它相关文章!

    本文共计2698个文字,预计阅读时间需要11分钟。

    React Native中RecyclerListView如何高效实现长列表滚动与优化?

    目录 + RecyclerListView 的介绍与使用

    1.安装

    2.概述和功能

    3.RecyclerListView 的使用

    React Native中RecyclerListView如何高效实现长列表滚动与优化?

    1. dataProvider 2. LayoutProvider 3. rowRenderer 4. onEndReached 5. onEndReachedThreshold 6. extendedState 7. scrollViewProps

    目录
    • recyclerlistview的介绍与使用
      • 1.安装
      • 2.概述和功能
      • 3. RecyclerListView的使用
        • 1、dataProvider
        • 2、LayoutProvider
        • 3、rowRenderer
        • 4、onEndReached
        • 5、onEndReachedThreshold
        • 6、extendedState
        • 7、scrollViewProps
    • RecyclerListView所有属性

      recyclerlistview的介绍与使用

      1.安装

      npm install --save recyclerlistview 或者: yarn add recyclerlistview

      2.概述和功能

      RecyclerListView 是一个高性能的列表(listview)组件,同时支持 React NativeWeb ,并且可用于复杂的列表。RecyclerListView 组件的实现灵感,来自于 Android RecyclerView原生组件及iOS UICollectionView原生组件。

      RecyclerListView使用“cell recycling”来重用不再可见的视图来呈现项目,而不是创建新的视图对象。 对象的创建非常昂贵并且带有内存开销,这意味着当您滚动列表时内存占用量不断增加。 从内存中释放不可见的项目是另一种技术,但这会导致创建更多的对象和大量的垃圾收集。 回收是渲染无限列表的最佳方式,不会影响性能或内存效率。

      为什么需要RecyclerListView

      我们知道,React Native 的其他列表组件如ListView,会一次性创建所有的列表单元格——cell。如果列表数据比较多,则会创建很多的视图对象,而视图对象是非常消耗内存的。所以,ListView组件,对于我们业务中的这种无限列表,基本上是不可以用的。

      对于React Native 官方提供的高性能的列表组件FlatList, 在Android设备上的表现,并不是十分友好。它的实现原理,是将列表中不在可视区域内的视图,进行回收,然后根据页面的滚动,不断的渲染出现在可视区域内的视图。这里需要注意的是,FlatList是将不可见的视图回收,从内存中清除了,下次需要的时候,再重新创建。这就要求设备在滚动的时候,能快速的创建出需要的视图,才能让列表流畅的展现在用户面前。而问题也就出现在这里,Android设备因为老化等原因,计算力等跟不上,加之React Native 本身 JS 层与 Native 层之间交互的一些问题(这里不做深入追究),导致创建视图的速度达不到使列表流畅滚动的要求。

      那怎样来解决这样的问题呢?

      RecyclerListView 受到 Android RecyclerViewiOS UICollectionView 的启发,进行两方面的优化:

      • 仅创建可见区域的视图,这步与FlatList是一致的。
      • cell recycling,重用单元格,这个做法是FlatList缺乏的。

      对于程序来说,视图对象的创建是非常昂贵的,并且伴随着内存的消耗。意味着如果不断的创建视图,在列表滚动的过程中,内存占用量会不断增加。FlatList中将不可见的视图从内存中移除,这是一个比较好的优化手段,但同时也会导致大量的视图重新创建以及垃圾回收。

      RecyclerListView 通过对不可见视图对象进行缓存及重复利用,一方面不会创建大量的视图对象,另一方面也不需要频繁的创建视图对象和垃圾回收。

      基于这样的理论,所以RecyclerListView的性能是会优于FlatList的。

      3. RecyclerListView的使用

      属性:

      1、dataProvider

      首先需要定义一个数据驱动方法

      let dataProvider = new DataProvider((r1, r2) => { return r1 !== r2; })

      定义完成之后去初始化数据

      // 列表数据 const [JRecyclerData, setJRecyclerData] = useState(_dataProvider.cloneWithRows(data));

      cloneWithRows

      • 想要更新列表的dataProvider数据也就是(DataSource)必须每次通过cloneWithRows这个来重新挂载datasource的值。
      • clone方法会自动提取新数据并进行逐行对比(使用rowHasChanged方法中的策略),这样列表就知道哪些行需要重新渲染了。

      2、LayoutProvider

      定义列表布局

      在这之前我们可以根据我们的业务场景,规划处几类的布局,然后自定义每种布局的类型来区分。

      //表示列表中会出现三种ui类型的item const ViewTypes = { FULL: 0, HALF_LEFT: 1, HALF_RIGHT: 2 }

      下面就可以来区分布局了

      • 为了进行cell-recycling,RecyclerListView要求对每个cell(通常也叫Item)定义一个type,根据type设置cell的dim.widthdim.height

      //第一个函数是定义item的ui类型,第二个是定义item的高宽 this._layoutProvider = new LayoutProvider( index => { if (index % 3 === 0) { return ViewTypes.FULL; } ... }, (type, dim) => { switch (type) { case ViewTypes.HALF_LEFT: dim.width = width / 2; dim.height = 160; break; ... } } )

      3、rowRenderer

      rowRenderer负责渲染一个cell,同样是根据type来进行渲染:

      _rowRenderer(type, data) { switch (type) { case ViewTypes.HALF_LEFT: return ( <CellContainer style={styles.containerGridLeft}> <Text>Data: {data}</Text> </CellContainer> ); ... } }

      例子:

      /*** * To test out just copy this component and render in you root component */ export default class RecycleTestComponent extends React.Component { constructor(args) { super(args); let { width } = Dimensions.get("window"); //Create the data provider and provide method which takes in two rows of data and return if those two are different or not. let dataProvider = new DataProvider((r1, r2) => { return r1 !== r2; }); //Create the layout provider //First method: Given an index return the type of item e.g ListItemType1, ListItemType2 in case you have variety of items in your list/grid //Second: Given a type and object set the height and width for that type on given object //If you need data based check you can access your data provider here //You'll need data in most cases, we don't provide it by default to enable things like data virtualization in the future //NOTE: For complex lists LayoutProvider will also be complex it would then make sense to move it to a different file this._layoutProvider = new LayoutProvider( index => { if (index % 3 === 0) { return ViewTypes.FULL; } else if (index % 3 === 1) { return ViewTypes.HALF_LEFT; } else { return ViewTypes.HALF_RIGHT; } }, (type, dim) => { switch (type) { case ViewTypes.HALF_LEFT: dim.width = width / 2 - 0.0001; dim.height = 160; break; case ViewTypes.HALF_RIGHT: dim.width = width / 2; dim.height = 160; break; case ViewTypes.FULL: dim.width = width; dim.height = 140; break; default: dim.width = 0; dim.height = 0; } } ); this._rowRenderer = this._rowRenderer.bind(this); //Since component should always render once data has changed, make data provider part of the state this.state = { dataProvider: dataProvider.cloneWithRows(this._generateArray(300)) }; } _generateArray(n) { let arr = new Array(n); for (let i = 0; i < n; i++) { arr[i] = i; } return arr; } //Given type and data return the view component _rowRenderer(type, data) { //You can return any view here, CellContainer has no special significance switch (type) { case ViewTypes.HALF_LEFT: return ( <CellContainer style={styles.containerGridLeft}> <Text>Data: {data}</Text> </CellContainer> ); case ViewTypes.HALF_RIGHT: return ( <CellContainer style={styles.containerGridRight}> <Text>Data: {data}</Text> </CellContainer> ); case ViewTypes.FULL: return ( <CellContainer style={styles.container}> <Text>Data: {data}</Text> </CellContainer> ); default: return null; } } render() { return <RecyclerListView layoutProvider={this._layoutProvider} dataProvider={this.state.dataProvider} rowRenderer={this._rowRenderer} />; } } const styles = { container: { justifyContent: "space-around", alignItems: "center", flex: 1, backgroundColor: "#00a1f1" }, containerGridLeft: { justifyContent: "space-around", alignItems: "center", flex: 1, backgroundColor: "#ffbb00" }, containerGridRight: { justifyContent: "space-around", alignItems: "center", flex: 1, backgroundColor: "#7cbb00" } };

      页面效果:

      但是在实际的业务开发中肯定不会是这么简单的,一般都会用到分页,下拉刷新什么的,下面介绍几个比较常用的属性:

      4、onEndReached

      列表触底是触发,一般是用来做上拉加载更过数据的时候来使用的

      <RecyclerListView layoutProvider={this._layoutProvider} dataProvider={this.dataProvider.cloneWithRows(this.state.infoList)} rowRenderer={this._rowRenderer} onEndReached={this._onLoadMore} />

      5、onEndReachedThreshold

      列表距离底部多大距离时触发onEndReached的回调,这个填写的是具体的像素值,与FlatList是有区别的,FlatList填写的是百分比

      <RecyclerListView layoutProvider={this._layoutProvider} dataProvider={this.dataProvider.cloneWithRows(this.state.infoList)} rowRenderer={this._rowRenderer} onEndReached={this._onLoadMore} onEndReachedThreshold={50} />

      6、extendedState

      在更新目前列表渲染以外的数据时,可以使用此属性更新状态,以便绘制出新的列表,并且不再重新渲染以前的列表数据

      <RecyclerListView layoutProvider={this._layoutProvider} dataProvider={this.dataProvider.cloneWithRows(this.state.infoList)} rowRenderer={this._rowRenderer} onEndReached={this._onLoadMore} onEndReachedThreshold={50} extendedState={this.state} />

      7、scrollViewProps

      继承scrollView的属性,RecyclerListView本身是不具有刷新属性的,要想使用刷新功能,就可以继承scrollView的下拉刷新

      <RecyclerListView scrollViewProps={{ refreshControl: ( <RefreshControl refreshing={this.state.loading} onRefresh={async () => { this.setState({ loading: true }); await this.getInfo(); this.setState({ loading: false }); }} /> ) }} />

      下面看一下完整的例子:

      import React, { Component } from "react"; import { View, Text, Dimensions, StyleSheet, RefreshControl, Alert } from "react-native"; import { RecyclerListView, DataProvider, LayoutProvider } from "recyclerlistview"; import WBCST from "./../../rn-app"; const ViewTypes = { FULL: 0 }; const { width } = Dimensions.get("window"); const styles = StyleSheet.create({ container: { flexDirection: "row", justifyContent: "space-between", // alignItems: "center", flex: 1, backgroundColor: "#fff", // borderWidth: 1, borderColor: "#dddddd", margin: 15, marginTop: 0, padding: 15 }, topicLeft: { width: width - 210, marginRight: 10 }, topicRight: { backgroundColor: "#f5f5f5", width: 140, height: 140, padding: 15 }, topicTitle: { color: "#000", fontSize: 16, fontWeight: "700", lineHeight: 28 }, topicContext: { color: "#999", fontSize: 12, lineHeight: 18, marginTop: 10 }, topicNum: { fontSize: 14, marginTop: 20 }, topicRightText: { fontSize: 14, color: "#666" } }); export default class RecycleTestComponent extends Component { constructor(props) { super(props); this.dataProvider = new DataProvider((r1, r2) => { return r1 !== r2; }); let { width } = Dimensions.get("window"); this._layoutProvider = new LayoutProvider( (index) => { return ViewTypes.FULL; }, (type, dim) => { dim.width = width; dim.height = 190; } ); this.state = { pagenum: 1, infoList: [], loading: false, isLoadMore: false }; } getInfo = () => { let num = this.state.pagenum; let info = this.state.infoList; WBCST.getFetch("app.58.com/api/community/aggregatepage/tabs/topic", { pagesize: 20, pagenum: num }).then((res) => { if (res) { let loadMore = false; if (num == 1) { if (res.data.questions.length == 20) { loadMore = true; } this.setState({ isLoadMore: loadMore, infoList: res.data.questions }); } else { // info.concat(res.data.questions); if (res.data.questions.length < 20) { loadMore = false; } else { loadMore = true; } this.setState({ isLoadMore: loadMore, infoList: this.state.infoList.concat(res.data.questions) }); } } }); }; _rowRenderer = (type, data) => { return ( <View style={styles.container}> <View style={styles.topicLeft}> <Text numberOfLines={2} style={styles.topicTitle}> {data.topic.title} </Text> <Text numberOfLines={2} style={styles.topicContext}> {data.topic.context} </Text> <Text style={styles.topicNum}> {data.topic.pn} 人参与此话题 </Text> </View> <View style={styles.topicRight}> <Text style={styles.topicRightText}>{data.user.name}</Text> <Text style={[{ marginTop: 10 }, styles.topicRightText]}>{data.title}</Text> </View> </View> ); }; _renderFooter = () => { return ( <View> <Text>上拉加载更多</Text> </View> ); }; _onLoadMore = () => { // Alert.alert(JSON.stringify("num")); if (!this.state.isLoadMore) { return; } let num = this.state.pagenum; num = num + 1; this.setState( { pagenum: num }, () => { // Alert.alert(JSON.stringify(num)); this.getInfo(); } ); }; componentDidMount = () => { this.getInfo(); }; render() { return ( <RecyclerListView layoutProvider={this._layoutProvider} dataProvider={this.dataProvider.cloneWithRows(this.state.infoList)} rowRenderer={this._rowRenderer} extendedState={this.state} onEndReached={this._onLoadMore} onEndReachedThreshold={50} // renderFooter={this._renderFooter} scrollViewProps={{ refreshControl: ( <RefreshControl refreshing={this.state.loading} onRefresh={async () => { this.setState({ loading: true }); // analytics.logEvent("Event_Stagg_pull_to_refresh"); await this.getInfo(); this.setState({ loading: false }); }} /> ) }} /> ); } }

      效果图:

      RecyclerListView所有属性

      以上就是ReactNative系列之Recyclerlistview使用详解的详细内容,更多关于ReactNative使用Recyclerlistview的资料请关注易盾网络其它相关文章!