您现在的位置是:网站首页> 编程资料编程资料
React Native系列之Recyclerlistview使用详解_React_
2023-05-24
353人已围观
简介 React Native系列之Recyclerlistview使用详解_React_
recyclerlistview的介绍与使用
1.安装
npm install --save recyclerlistview 或者: yarn add recyclerlistview
2.概述和功能
RecyclerListView 是一个高性能的列表(listview)组件,同时支持 React Native 和 Web ,并且可用于复杂的列表。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 RecyclerView 和 iOS 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.width和dim.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 ( Data: {data} ); ... } } 例子:
/*** * 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 ( Data: {data} ); case ViewTypes.HALF_RIGHT: return ( Data: {data} ); case ViewTypes.FULL: return ( Data: {data} ); default: return null; } } render() { return ; } } 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
列表触底是触发,一般是用来做上拉加载更过数据的时候来使用的
5、onEndReachedThreshold
列表距离底部多大距离时触发onEndReached的回调,这个填写的是具体的像素值,与FlatList是有区别的,FlatList填写的是百分比
6、extendedState
在更新目前列表渲染以外的数据时,可以使用此属性更新状态,以便绘制出新的列表,并且不再重新渲染以前的列表数据
7、scrollViewProps
继承scrollView的属性,RecyclerListView本身是不具有刷新属性的,要想使用刷新功能,就可以继承scrollView的下拉刷新
{ 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 -
相关内容
- 微信小程序view与scroll-view组件的使用介绍_javascript技巧_
- 在react中使用windicss的问题_React_
- React中过渡动画的编写方式实例详解_javascript技巧_
- 用electron 打包发布集成vue2.0项目的操作过程_vue.js_
- vue中动态添加style样式的几种写法总结_vue.js_
- IntersectionObserver判断是否在可视区域详解_javascript技巧_
- vue中post请求报400的解决方案_vue.js_
- React Context源码实现原理详解_React_
- vue 页面卡死,点击无反应的问题及解决_vue.js_
- node 安装 windows-build-tools全过程_node.js_
点击排行
本栏推荐
