https://github.com/Flipkart/recyclerlistview
概述和功能
RecyclerListView 是一个高性能的列表(listview)组件,同时支持 React Native 和 Web ,并且可用于复杂的列表。RecyclerListView 组件的实现灵感,来自于 Android RecyclerView原生组件及iOS UICollectionView原生组件。
优点
解决了FlatList快速滚动出现白屏,列表数据很大的时候安卓滚动卡顿的问题
缺点
需要提前计算并设置layout。
原理
RecyclerListView使用“cell recycling”来重用不再可见的视图来呈现项目,而不是创建新的视图对象。 对象的创建非常昂贵并且带有内存开销,这意味着当您滚动列表时内存占用量不断增加。 从内存中释放不可见的项目是另一种技术,但这会导致创建更多的对象和大量的垃圾收集。 回收是渲染无限列表的最佳方式,不会影响性能或内存效率。
为什么需要RecyclerListView
我们知道,React Native 的其他列表组件如ListView,会一次性创建所有的列表单元格——cell。如果列表数据比较多,则会创建很多的视图对象,而视图对象是非常消耗内存的。所以,ListView组件,对于我们业务中的这种无限列表,基本上是不可以用的。
对于React Native 官方提供的高性能的列表组件FlatList, 在Android设备上的表现,并不是十分友好。它的实现原理,是将列表中不在可视区域内的视图,进行回收,然后根据页面的滚动,不断的渲染出现在可视区域内的视图。这里需要注意的是,FlatList是将不可见的视图回收,从内存中清除了,下次需要的时候,再重新创建。这就要求设备在滚动的时候,能快速的创建出需要的视图,才能让列表流畅的展现在用户面前。而问题也就出现在这里,Android设备因为老化等原因,计算力等跟不上,加之React Native 本身 JS 层与 Native 层之间交互的一些问题(这里不做深入追究),导致创建视图的速度达不到使列表流畅滚动的要求。当数据很大的时候就会出现滑动卡顿的现象。
1、先安装 yarn add recyclerlistview
const ViewTypes = {
HEADER : 0,
CELL : 1
}
const HEADER_HEIGHT1 = screen.scaleSize( 1850)
const HEADER_HEIGHT2 = screen.scaleSize(2510)
const CELL_HEIGHT = screen.scaleSize( 420 )
let pageNo = 1;//当前第几页
let totalPage = 50;//总的页数
class Home extends Component<Props> {
constructor(props) {
super(props);
this._renderRow = this._renderRow.bind(this)
this.getLayoutProvider = this.getLayoutProvider.bind(this)
}
getLayoutProvider(showRemind){
let layoutProvider = new LayoutProvider((i)=>{
if(i == 0){
return ViewTypes.HEADER
}
return ViewTypes.CELL
},(type,dim)=>{
dim.width = screen.width
switch (type) {
case ViewTypes.HEADER:
dim.height = showRemind ? HEADER_HEIGHT2 : HEADER_HEIGHT1
break;
case ViewTypes.CELL:
dim.height = CELL_HEIGHT
break;
}
})
return layoutProvider
}
state = {
loading:false,
data:[0],
tehuiData:[],
monthData:[],
remindList:[],
showFoot:2,// 控制foot, 0:隐藏footer 1:已加载完成,没有更多数据 2:显示加载中
layoutProvider:this.getLayoutProvider(false)
}
_renderRow(type,data){
switch (type) {
case ViewTypes.HEADER:
return this._renderHeaderView()
case ViewTypes.CELL:
return (
<HouseCell
item={data}
onPress={(item)=>{
this.props.navigation.navigate('Detail',{houseId:item.id,datafrom:item.datafrom})
}}
/>
)
default:
return null;
}
}
_keyExtractor = (item,index) => `index_${index}`;
//为空时
listEmptyComponent() {
return (
<View style={{ width: screen.width, height: screen.height - 140,
justifyContent: 'center', alignItems: 'center',}}>
<Text style={{marginTop: 15, fontSize: 18, color: '#999999',}}>没有数据</Text>
</View>
);
}
render() {
let content = (
<LoadingView />
)
if(this.state.data.length > 0 && this.state.monthData.length > 0 && this.state.tehuiData.length > 0
){
let dataProvider = new DataProvider((r1,r2)=>{
return r1 !== r2
}).cloneWithRows(this.state.data)
return (
<RecyclerListView
dataProvider={dataProvider}
rowRenderer={this._renderRow}
layoutProvider={this.state.layoutProvider}
renderFooter={()=>(
<ListFooterView showFoot={this.state.showFoot}/>
)}
onEndReached={this._onEndReached.bind(this)}
onEndReachedThreshold={0.1}
scrollViewProps={{
refreshControl: (
<RefreshControl
refreshing={this.state.loading}
onRefresh={ this.getInitData}
/>
)
}}
/>)
}
}
_onEndReached(){
if(this.pageNo === 1){
return;
}
console.log('滑到底部了')
//如果是正在加载中或没有更多数据了,则返回
if(this.state.showFoot !== 0 ){
return ;
}
//如果当前页大于或等于总页数,那就是到最后一页了,返回
if((pageNo!=1) && (pageNo>=totalPage)){
return;
} else {
pageNo++;
}
//底部显示正在加载更多数据
this.setState({showFoot:2});
//获取数据
this.fetchData( );
}
}
网友评论