react native 开发APP(六)网络请求,列表的使用

官网 https://reactnative.cn/

项目下载地址:https://github.com/hebiao6446/DemoProject
陆续更新中。。。

在移动端开发的时候,我们基本上都会用到列表,

React native iOS Android
ListView UITableView RecyclerView

说到列表,那么必然跟网络请求有关系,网络这块那么肯定,所以我们来搞一搞网络请求。。。。

1.react native的网络请求

网络请求这块,react native是比较良心的, 自带了网络请求框架

React native iOS Android
fetch AFNetworking 这尼玛没统一

通常一个网络请求的三要素: 请求方式(GET,POST),请求地址,请求参数 (文件上传下载另说) 我们用react native来搞一搞网络请求一把。通常情况下,网络请求的三要素:请求方式(GET,POST等),请求地址,请求参数,大部分网络请求都是异步的,并且都是JSON格式的数据返回结果,那么这个就简单了。。。。 我们直接上代码,封装之后的代码

postHttp(url,postDic):Promise{
      return fetch(url,{
            method: 'POST',
            headers: {
                Accept: 'application/json',
                'Content-Type': 'application/json',
            },
            body: JSON.stringify(postDic),
        }).then((response) =>
        {
            return response.json()
        });
    }

上面是一个简单的POST请求,没什么好说的,使用的时候照抄就行了,但是我要说的是Promise (这里有介绍链接 https://www.jianshu.com/p/063f7e490e9a)多了就不解释了。。
来看代码

import BaseComponet from "./BaseComponet";
import {Image, StyleSheet, View} from "react-native";
import React from "react";
import {createStackNavigator} from "react-navigation-stack";
import HbColor from "../utils/HbColor";

class SecondView  extends BaseComponet{
    render(){
        return (
            
            
        );
    }
    componentDidMount(): void {
        this.getDaraFromUrl();
    }

    getDaraFromUrl():void{
        let url = "https://way.jd.com/jisuapi/get?appkey=cecba3ef670321c25c7246174f586113";
        let para = {
            start:1,
            num:20,
            channel:"头条"
        };
        this.postHttp(url,para).then((res)=>{
            console.log(res);
        }).catch((e)=>{
            console.log(e);
        });
    }

    postHttp(url,postDic):Promise{
          return fetch(url,{
              method: 'POST',
              headers: {
                  Accept: 'application/json',
                  'Content-Type': 'application/json',
              },
              body: JSON.stringify(postDic),
          }).then((response) =>
          {
              return response.json()
          });
    }
}

我们来看下重点的代码

getDaraFromUrl():void{
       let url = "https://way.jd.com/jisuapi/get?appkey=cecba3ef670321c25c7246174f586113";
        let para = {
            start:1,
            num:20,
            channel:"头条"
        };
        this.postHttp(url,para).then((res)=>{
            console.log(res);
        }).catch((e)=>{
            console.log(e);
        });
    }

这里面有个then 和 catch , 用一个最通俗的解释就是 请求成功用then ,请求失败用 catch

请求成功 请求失败,断网,超时,异常
then catch

以上网络请求基本满足小厂的使用, 关于文件上传和下载,网络认证等 我会在后面讲到,文件上传和下载,认证跟简单的接口调用还是有点区别的

2.react native的列表使用(FlatList)

FlatList 是react native 良心自带的 https://reactnative.cn/docs/0.44/flatlist.html

React native iOS Android
FlatList UITableView RecyclerView

我们来搞一个从网络请求数据放在列表上显示的一个事情,我们先看看一个静态的效果
react native 开发APP(六)网络请求,列表的使用_第1张图片
首先我们把列表对应的Cell(或者Item)布局贴出来

import {Image, StyleSheet, Text, TouchableOpacity, View} from "react-native";
import React, {Component} from "react";
export default class SecondViewCell extends Component{
    render(){
        let imgUrl = "https://p.ivideo.sina.com.cn/video/331/403/567/331403567.jpg";
        return (
            {
                this.props.onItemClick();
            }}>
                
                    
                    
                        测试列表内容
                        红星视频
                        2020-04-10 10:22:00
                    
                
            
        );
    }
}
const styles = StyleSheet.create({
    container:{
        height:90,
        flex: 1,
        flexDirection:'row',
        justifyContent:'flex-start',
        backgroundColor: '#ffffff',
    },
    container1:{
        flex: 1,
        flexDirection: 'column',
        justifyContent: 'space-between',
        // backgroundColor:"#f2f2f2",
        margin:10
    },

});

然后我们来分析下FlatList的使用,这里我直接贴上Flatlist的代码并逐个讲解了

  (index + '1')}   列表对应的key属性,基本用不上
                    refreshControl={   /// 列表对应的下拉刷新的组件  
                        
                    }
                    onEndReachedThreshold={0.2}    决定当距离内容最底部还有多远时触发onEndReached回调。
                    onScrollBeginDrag={()=>{
                        this.state.canLoadMore = false;  /// 防止onEndReachedThreshold 被重复调用
                    }}
                    onScrollEndDrag={()=>{
                        this.state.canLoadMore = true; /// 防止onEndReachedThreshold 被重复调用
                    }}
                    onMomentumScrollBegin={()=>{
                        this.state.canLoadMore = false; /// 防止onEndReachedThreshold 被重复调用
                    }}
                    onMomentumScrollEnd={()=>{
                        this.state.canLoadMore = true; /// 防止onEndReachedThreshold 被重复调用
                    }}
                    ListFooterComponent={()=>this.loadMoreView()}//上拉加载更多视图
                    ItemSeparatorComponent = {   列表对应的分割线
                        ()=>{
                            return ()
                        }
                    }
                    onEndReached={()=>{
                        // 数据少
                        if (this.state.footerStatus != 1) return;
                        // if (!this.state.canLoadMore) return;
                        this.setState({
                            pageNow:this.state.pageNow+1,
                        },()=>{
                            this.getDaraFromUrl();
                        })

                    }}
                />

FlatList的基本属性我们已经说完了,我们现在进入实战阶段,从网络上获取数据
react native 开发APP(六)网络请求,列表的使用_第2张图片
我们接如正式的数据看下效果 , 如下图

其实挺简单的,我们只需要把请求的数据跟 state 里面的数据关联起来就可以了。。。

getDaraFromUrl():void{
        let url = "https://way.jd.com/jisuapi/get?appkey=cecba3ef670321c25c7246174f586113";
        let para = {
            start:this.state.start,
            num:this.state.num,
            channel:"头条"
        };
        this.postHttp(url,para).then((res)=>{
            if (res.result.status == 0){
                let dataList = res.result.result.list;
                let newList  = this.state.arrList.concat(dataList);
                let ftStatus =  dataList.length == this.state.num ? 1:2;
                let ddList = this.state.start == 1 ? dataList : newList;
                this.setState({
                    arrList:ddList,
                    footerStatus:ftStatus,
                    isRefreshing:false,
                    netError:false,
                })
            }else {
                this.setState({
                    isRefreshing:false,
                    netError:false,
                })
            }
            
        }).catch((e)=>{
            this.setState({
                isRefreshing:false,
                netError:true,
            })
        });
    }

刚刚上面提到有个地方 ,需要重点说下

  this.setState({
           start:this.state.start+1,
 },   ()=>{
          this.getDaraFromUrl();
 })

分页请求在实际情况下是非常常见的,分页是的时候也就是页面+1就可以, 那么在 react native 里面,我要说的重点来了 this.setState设置属性的值是个异步的过程,也就是设置成功只有会有回调函数
这些都不重要了 。。。。

3. FlatList 无数据,无网络,加载中页面

目前市场上的APP都有这种需求 。。 这个就不解释了 。。。我先把这几个页面列出来

得出下面结论

FlatList data为空 FlatList data 不为空
开始加载数据 显示加载动画页面 显示正常列表页面,提示加载中
加载数据完成 显示无数据页面 显示正常列表页面,提示加载完成
无网络请求失败 显示无网络页面 显示正常列表页面,提示网络错误

也就是只有当FlatList data为空的时候回出现不同的页面
直接上代码

render(){
        return (
            

                {this.state.arrList.length > 0 ?
                 (index + '1')}
                    refreshControl={
                        
                    }
                    onEndReachedThreshold={0.2}
                    onScrollBeginDrag={()=>{
                        this.state.canLoadMore = false;
                    }}
                    onScrollEndDrag={()=>{
                        this.state.canLoadMore = true;
                    }}
                    onMomentumScrollBegin={()=>{
                        this.state.canLoadMore = false;
                    }}
                    onMomentumScrollEnd={()=>{
                        this.state.canLoadMore = true;
                    }}
                    ListFooterComponent={()=>this.loadMoreView()}//上拉加载更多视图
                    ItemSeparatorComponent = {
                        ()=>{
                            return ()
                        }
                    }
                    onEndReached={()=>{
                        // 数据少
                        if (this.state.footerStatus != 1) return;
                        // if (!this.state.canLoadMore) return;
                        this.setState({
                            start:this.state.start+1,
                        },()=>{
                            this.getDaraFromUrl();
                        })
                    }}
                />: (this.state.netError ?  : (this.state.isRefreshing ?  :  )) }
            
        );
    }
4. 完整的网络请求 和 FlatList 无数据,无网络,加载中页面,列表点击item 代码
import BaseComponet from "./BaseComponet";
import {Image, StyleSheet, View,FlatList,RefreshControl,ActivityIndicator,Text} from "react-native";
import React from "react";
import {createStackNavigator} from "react-navigation-stack";
import HbColor from "../utils/HbColor";
import SecondViewCell from "./SecondViewCell";


import NetErrorView from "../subview/NetErrorView";
import LoadDataView from "../subview/LoadDataView";
import NodataView from "../subview/NodataView";

class SecondView  extends BaseComponet{
    constructor(props){
        super(props);
        this.state={
            start:1,
            num:10,
            arrList:[],
            netError:false,
            isRefreshing:false,
            footerStatus:0,
            canLoadMore:false,
        };
        this.refreshData = this.refreshData.bind(this);
    }
    refreshData():void{

        this.setState({
            start:1,
            isRefreshing:true,
        },()=>{
            this.getDaraFromUrl();
        });
    }
    render(){
        return (
            

                {this.state.arrList.length > 0 ?
                 (index + '1')}
                    refreshControl={
                        
                    }
                    onEndReachedThreshold={0.2}
                    onScrollBeginDrag={()=>{
                        this.state.canLoadMore = false;
                    }}
                    onScrollEndDrag={()=>{
                        this.state.canLoadMore = true;
                    }}
                    onMomentumScrollBegin={()=>{
                        this.state.canLoadMore = false;
                    }}
                    onMomentumScrollEnd={()=>{
                        this.state.canLoadMore = true;
                    }}
                    ListFooterComponent={()=>this.loadMoreView()}//上拉加载更多视图
                    ItemSeparatorComponent = {
                        ()=>{
                            return ()
                        }
                    }
                    onEndReached={()=>{
                        // 数据少
                        if (this.state.footerStatus != 1) return;
                        // if (!this.state.canLoadMore) return;
                        this.setState({
                            start:this.state.start+1,
                        },()=>{
                            this.getDaraFromUrl();
                        })
                    }}
                />: (this.state.netError ?  : (this.state.isRefreshing ?  :  )) }


            
        );
    }
    componentDidMount(): void {
        this.getDaraFromUrl();
    }

    renderItemView({item}) {
        return (
            {
                    console.log(item.title)
            }}  />
        );
    }


    loadMoreView(){
        if (this.state.footerStatus == 0 ){
            return null;
        }else if (this.state.footerStatus == 1){
            return (
                
                正在加载更多
            );
        }else {
            return (
                没有更多数据
            );
        }
    }
    getDaraFromUrl():void{
        let url = "https://way.jd.com/jisuapi/get?appkey=cecba3ef670321c25c7246174f586113";
        let para = {
            start:this.state.start,
            num:this.state.num,
            channel:"头条"
        };
        this.postHttp(url,para).then((res)=>{
            if (res.result.status == 0){
                let dataList = res.result.result.list;
                let newList  = this.state.arrList.concat(dataList);
                let ftStatus =  dataList.length == this.state.num ? 1:2;
                let ddList = this.state.start == 1 ? dataList : newList;
                this.setState({
                    arrList:ddList,
                    footerStatus:ftStatus,
                    isRefreshing:false,
                    netError:false,
                })


            }else {
                this.setState({
                    isRefreshing:false,
                    netError:false,
                })
            }

        }).catch((e)=>{
            this.setState({
                isRefreshing:false,
                netError:true,
            })
        });
    }

    postHttp(url,postDic):Promise{
          return fetch(url,{
              method: 'POST',
              headers: {
                  Accept: 'application/json',
                  'Content-Type': 'application/json',
              },
              body: JSON.stringify(postDic),
          }).then((response) =>
          {
              return response.json()
          });
    }
}
const styles = StyleSheet.create({
    contain:{
        backgroundColor:'#ffffff',
        flex:1,
    },
});

const SecondNavi = createStackNavigator({
    Second: {
        screen: SecondView,
        navigationOptions: {
            title: '第2页',
            headerStyle: {
                backgroundColor: HbColor.COLOR_BLUE,
            },
            headerTintColor: '#ffffff',
        },
    },
}, {
    navigationOptions: ({
                            navigation
                        }) => ({
        tabBarVisible: navigation.state.index > 0 ? false : true,
    })
});

export default SecondNavi;

5. Android 使用GIF需要注意的事项

这是一个关于Image使用的文章 https://www.hangge.com/blog/cache/detail_1542.html

(1)React Native 默认支持 JPG、PNG 格式。
(2)在 iOS 平台下,还支持 GIF、WebP 格式。
(3)在 Android 平台下,默认不支持 GIF、WebP 格式。可以通过修改 Android 工程设置让其支持这两种格式:

也就是 Android如果使用gif要导入一个库

dependencies {
  compile 'com.facebook.fresco:animated-gif:0.11.0'  //需要GIF动画支持添加本行语句
  compile 'com.facebook.fresco:webpsupport:0.11.0'  //需要WebP格式支持添加本行语句
  compile 'com.facebook.fresco:animated-webp:0.11.0'  //需要WebP动画支持添加本行语句
}

项目下载地址:https://github.com/hebiao6446/DemoProject
陆续更新中。。。

你可能感兴趣的:(react_native,IOS,Android)