Skip to content

Commit b63a6c7

Browse files
committed
refactor(ViewPager): replace ListView with FlatList
This should improve overall performance greatly. It might even prevent crashes on Android with galleries of large images.
1 parent 9fda746 commit b63a6c7

File tree

1 file changed

+17
-21
lines changed

1 file changed

+17
-21
lines changed

src/ViewPager.js

+17-21
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React, { PropTypes, PureComponent } from 'react';
2-
import { View, ListView, ViewPropTypes } from 'react-native';
2+
import { View, FlatList, ViewPropTypes } from 'react-native';
33
import Scroller from 'react-native-scroller';
44
import { createResponder } from 'react-native-gesture-responder';
55

@@ -46,8 +46,7 @@ export default class ViewPager extends PureComponent {
4646
this.onResponderMove = this.onResponderMove.bind(this);
4747
this.onResponderRelease = this.onResponderRelease.bind(this);
4848

49-
const ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
50-
this.state = { width: 0, height: 0, dataSource: ds.cloneWithRows([]) };
49+
this.state = { width: 0, height: 0 };
5150

5251
this.scroller = new Scroller(true, (dx, dy, scroller) => {
5352
if (dx === 0 && dy === 0 && scroller.isFinished()) {
@@ -56,7 +55,7 @@ export default class ViewPager extends PureComponent {
5655
}
5756
} else {
5857
const curX = this.scroller.getCurrX();
59-
this.refs['innerListView'] && this.refs['innerListView'].scrollTo({x: curX, animated: false});
58+
this.refs['innerFlatList'] && this.refs['innerFlatList'].scrollToOffset({ offset: curX, animated: false });
6059

6160
let position = Math.floor(curX / (this.state.width + this.props.pageMargin));
6261
position = this.validPage(position);
@@ -86,13 +85,8 @@ export default class ViewPager extends PureComponent {
8685
let {width, height} = e.nativeEvent.layout;
8786
let sizeChanged = this.state.width !== width || this.state.height !== height;
8887
if (width && height && sizeChanged) {
89-
// if layout changed, create a new DataSource instance to trigger renderRow
9088
this.layoutChanged = true;
91-
this.setState({
92-
width,
93-
height,
94-
dataSource: (new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2})).cloneWithRows([])
95-
});
89+
this.setState({ width, height });
9690
}
9791
}
9892

@@ -209,18 +203,22 @@ export default class ViewPager extends PureComponent {
209203
return this.scroller.getCurrX() - this.getScrollOffsetOfPage(this.currentPage);
210204
}
211205

212-
renderRow (rowData, sectionID, rowID, highlightRow) {
206+
keyExtractor (item, index) {
207+
return index;
208+
}
209+
210+
renderRow ({ item, index }) {
213211
const { width, height } = this.state;
214212
const { renderPage, pageMargin } = this.props;
215-
let page = renderPage(rowData, rowID);
213+
let page = renderPage(item, index);
216214

217215
const layout = { width: width, height: height, position: 'relative' };
218216
const style = page.props.style ? [page.props.style, layout] : layout;
219217

220218
let newProps = { ...page.props, ref: page.ref, style };
221219
const element = React.createElement(page.type, newProps);
222220

223-
if (pageMargin > 0 && rowID > 0) {
221+
if (pageMargin > 0 && index > 0) {
224222
// Do not using margin style to implement pageMargin.
225223
// The ListView seems to calculate a wrong width for children views with margin.
226224
return (
@@ -237,13 +235,11 @@ export default class ViewPager extends PureComponent {
237235
const { width, height } = this.state;
238236
const { pageDataArray, scrollEnabled, style, removeClippedSubviews, initialListSize, scrollViewStyle } = this.props;
239237

240-
let dataSource = this.state.dataSource;
241238
if (width && height) {
242239
let list = pageDataArray;
243240
if (!list) {
244241
list = [];
245242
}
246-
dataSource = dataSource.cloneWithRows(list);
247243
this.pageCount = list.length;
248244
}
249245

@@ -257,16 +253,16 @@ export default class ViewPager extends PureComponent {
257253
{...this.props}
258254
style={[style, { flex: 1 }]}
259255
{...gestureResponder}>
260-
<ListView
256+
<FlatList
261257
style={[{ flex: 1 }, scrollViewStyle]}
262-
ref={'innerListView'}
258+
ref={'innerFlatList'}
259+
keyExtractor={this.keyExtractor}
263260
scrollEnabled={false}
264261
horizontal={true}
265-
enableEmptySections={true}
266-
dataSource={dataSource}
267-
renderRow={this.renderRow}
262+
data={pageDataArray}
263+
renderItem={this.renderRow}
268264
onLayout={this.onLayout}
269-
removeClippedSubviews={ removeClippedSubviews }
265+
removeClippedSubviews={removeClippedSubviews}
270266
initialListSize={ initialListSize }
271267
/>
272268
</View>

0 commit comments

Comments
 (0)