zl程序教程

您现在的位置是:首页 >  前端

当前栏目

React Native ListView中图片加载优化处理(三)

React 处理 优化 图片 加载 native listview
2023-09-27 14:28:59 时间

尊重版权,未经授权不得转载

本项目来自wcandillon  文章来自江清清的技术专栏(http://www.lcode.org)

原文地址(需要翻墙):https://hackernoon.com/image-pipeline-with-react-native-listview-b92d4768b17c#.sbu3nxne8

在手机应用中,图片列表的滚动操作是非常常见的,而且这个功能一般用户的期望都比较高,需要很不错的用户体验。在上一篇文章中(点击进入),我们主要分享了如何实现React Native中的图片缓存,在本文中我将会给大家带来在图片列表滚动过程中如何进行优化ListView中的图片加载。

React Native交流10群:157867561,欢迎各位大牛,React Native技术爱好者加入交流!同时博客右侧欢迎微信扫描关注订阅号,移动技术干货,精彩文章技术推送!

例如:一个类似Instagram应用中的图片类目。当我们从服务器获取一页数据之后,刚开始当用户滚动列表到底部的时候,我们发送请求从服务器获取更多数据。其次,当一个图片项进入屏幕显示的时候,我们通过图片缓存模块获取并且显示图片。最终当该图片项滑出屏幕的时候,如果该图片还没有被显示与缓存,我们需要取消该图片下载来提供可见项处理优先级。

在下面的示例中,我们从firebase后端获取一页10条数据,当我们滑动列表到最底端的时候,我们通过触发onEndReached事件方法来获取新的一页数据。具体代码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
export default class Feed extends Component<{}, void > {
 
     currentPage = 1 ;
     pageSize = 10 ;
 
     feed: ListViewDataSource =
         new ListView.DataSource({ rowHasChanged: (r1, r2) => r1.id !== r2.id });
 
     loadPage() {
         firebase.database().ref( "/feed" )
             .limitToFirst( this .pageSize * this .currentPage)
             .once( "value" ).then(snapshot => {
                 this .currentPage++;
                 this .feed = this .feed.cloneWithRows(snapshot.val());
             });
     }
 
     componentWillMount() { this .loadFeed(); }
 
     render() {
         const {store} = this .props;
         return <ListView
             dataSource={store.feed}
             renderRow={row => <View><CachedImage source={{ uri: row.uri }} /></View> }
             onEndReached={() => this .loadFeed()}
         />;
     }
}

现在我们可以使用onChangeVisibleRows()方法来只加载可见列表项图片。我们来创建一个带有visible属性的Row组件,通过ref()回调保证每一项显示的列表行数据保持最新,最后在onChangeVisibleRows()方法,进行更新列表中每一项的visible属性状态是可见或者不可见。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
export default class Feed extends Component<{}, void > {
 
   //Keep a reference of all mounted Rows
   rows: { [id: string ]: any } = {};
 
   render() {
     return <ListView
       dataSource={store.feed}
       // We use ref to keep the reference of all mounted rows
       // The visible property will be set to true in onChangeVisibleRows()
       renderRow={row => <Row ref={el => this .rows[row.id] = el} visible={ false } row={row} />}
       onEndReached={() => this .loadFeed()}
       onChangeVisibleRows={(visibleRows, changedRows) => {
         _.forEach(changedRows[ "s1" ], (visible, index) => {
           // We get the reference of the mounted row
           //and set its property to true
           const id = this .feed.getRowData( 0 , index).id;
           this .rows[id].props.visible = visible;
         });
       }} />;
   }
}

在Row组件中,我们可以通过visible属性来挂载/卸载图片控制该隐藏或者显示。我们通过react-native-img-cache包加载显示图片。

?
1
2
3
4
5
6
7
8
export default class Row extends Component<RowProps, void > {
   render() {
     const {visible, row} = this .props;
     return <View>
       {visible && <CachedImage source={{ uri: row.pictureURI }} />}
     </View>;
   }
}

然后是最后一步,如果该Row变得不显示的时候,就会取消下载图片的HTPP请求。react-native-img-cache库依赖于react-native-fetch-blob库,可以同时实现下载图片功能和取消HTTP请求功能。具体实现如下:

?
1
2
3
if (!visible) {
   ImageCache.get().cancel(row.uri);
}

React Native交流10群:157867561,欢迎各位大牛,React Native技术爱好者加入交流!同时博客右侧欢迎微信扫描关注订阅号,移动技术干货,精彩文章技术推送!