React Native学习之网络状态与数据交互API

NetInfo网络连接状态

获取网络状态是异步的,使用js的Promise机制

Android平台的网络连接类型状态如下:

  • 1). NONE:设备没有网络连接
  • 2). BLUETOOTH:蓝牙数据连接
  • 3). DUMMY:虚拟数据连接
  • 4). ETHERNET:以太网数据连接
  • 5). MOBILE:手机移动网络数据连接
  • 6). MOBILE_DUN:拨号移动网络数据连接
  • 7). MOBILE_HIPRI:高权限的移动网络数据连接
  • 8). MOBILE_MMS:彩信移动网络数据连接
  • 9). MOBILE_SUPL:SUP网络数据连接
  • 10). VPN:虚拟网络连接,最低支持Android API 21版本
  • 11). WIFI:无线网络连接
  • 12). WIMAX:wimax网络连接
  • 13). UNKNOWN:未知网络数据连接

根据文档说明:除此之外的其他一些网络连接状态已经被Android API隐藏,但是我们可以在有需要的时候进行使用。

IOS平台的网络连接类型状态如下:

  • 1). none:设备没有联网
  • 2). wifi:设备联网并且是连接的wifi网络,或者当前是iOS模拟器
  • 3). cell:设备联网是通过连接Edge,3G,WiMax或者LET网络
  • 4). unknown:该检测发生异常错误或者网络状态无从知道

NetInfo有两个监听:

  • 网络状态改变的监听,回调当前网络的状态
  • 网络是否连接的监听,回调true或false

Android独有的特色:

  • NetInfo.isConnectionExpensive判断当前网络是否计费
  • AndroidManifest.xml文件中添加如下权限字段(需重新编译)
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

数据交互(网络请求与响应)

抓包工具

抓包工具:httpwatch

IE中打开httpwatch的方法:Shift+F2,步骤 Record Stop Clear

请求协议

通过http或https协议与网络服务器交互,react native集成了node-fetch包以支持开发者的这种需求

网络协议:http https

请求方法

网络请求方法:get post put delete head trace 等

Get 与 Post 的区别:

  • GET使用URL或Cookie传参。而POST将数据放在BODY中;
  • GET的URL会有长度上的限制,则POST的数据则可以非常大;
  • POST比GET安全,因为数据在地址栏上不可见。

建议:

  • Get方式的安全性较Post方式要差些,如果包含机密信息,建议使用Post数据提交方式;
  • 在请求数据查询时,建议用Get方式;而在做数据添加、修改或删除时,建议用Post方式;

消息头

准备需要传输的消息头:(标准消息头和自定义消息头)

React Native使用http协议框架支持Accept-Encoding: gzip, deflate格式编码,开发者不需要对此进行设置。

自定义消息头可以在一些约定好的http消息头中填入身份认证信息。

POST 提交数据方式

  • application/x-www-form-urlencoded:key1=val1&key2=val2
  • multipart/form-data:Map键值对数据,支持文件
  • application/json:JSON数据
  • text/xml:XML数据

网络访问 API - Fetch

React Native中的网络访问API:Fetch(推荐)、XMLHttpRequest

fetch是一个更好的网络API,它由标准委员会提出,并已经在Chrome中实现。它在React Native中也默认可以使用。fetch的返回值是一个Promise对象,你可以用两种办法来使用它:

  • 使用then和catch指定回调函数
  • 使用ES7的async/await语法发起一个异步调用

注:如果你的服务器无法识别POST multipart/form-data的数据格式,那么可以尝试传统的application/x-www-form-urlencoded格式:

map.body = 'username=test&password=test&act=signin';

其他请求参数配置

map.follow = 10; //设置请求允许的最大重定向次数,0为不允许重定向
map.timeout = 8000; //设置超时时间,0为没有超时时间,这个值在重定向时会被重置
map.size = 0; //设置请求回应中的消息体最大允许长度,0为没有限制

errTypeError: Network request failed

使用 fetch 发送 HTTP请求,如果出现错误:errTypeError: Network request failed

则必须添加请求头headers

let map = {
    method: 'GET',
    headers: {
        'Accept': 'text/html,application/xhtml+xml,application/xml,application/json,image/webp,*/*;',
        'Content-Type': 'text/plain;charset=UTF-8',
        'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.89 Safari/537.36',
    },
};

注意:如果使用fetch获取数据,无论使用的是GET方法,还是POST方法,都必须添加请求头headers。当请求为GET时不能包含body,当请求为POST时必须包含body。

网络访问 API - XMLHttpRequest

XMLHttpRequest 的实现几乎跟Web一样,唯一的区别就是(安全机制) React Native 中的XMLHttpRequest不存在跨域的限制,而是作为全局 API 实现的,你可以访问任何网站。但是,XMLHttpRequest基于iOS网络的。

let request=new XMLHttpRequest();
request.onreadystatechange = (e)=>{
    if(request.readyState!==4) {
        return ;
    }
    if(request.status===200) {
        alert(request.resonsesText);
    } else {
        alert('出错啦');
    }
};
request.open('GET','http://www.rnapp.cc/');
request.send();

范例:

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 * @flow
 */

import React, { Component } from 'react';
import {
  AppRegistry,
  StyleSheet,
  Text,
  NetInfo,
  ToastAndroid,
  View
} from 'react-native';

class RNAPP extends Component {
    constructor(props) {
        super(props);
        this.state = {
            isConnected: null,
            connectionInfo: null,
        };
    }

    componentDidMount() {
        //网络是否连接的监听
        NetInfo.isConnected.addEventListener(
            'isConnected',
            this._handleConnectivityChange
        );

        //网络状态变化的监听
        NetInfo.addEventListener(
            'statusChange',
            this._handleNetStatusChange
        );

        //检测网络是否连接
        NetInfo.isConnected.fetch().done(
            (isConnected) => { this.setState({ isConnected: isConnected }); }
        );

        //检测网络连接状态
        NetInfo.fetch().done(
            (connectionInfo) => { this.setState({ connectionInfo: connectionInfo }); }
        );
    }

    componentWillUnmount() {
        //卸载两个监听
        NetInfo.isConnected.removeEventListener(
            'isConnected',
            this._handleConnectivityChange
        );
        NetInfo.removeEventListener(
            'statusChange',
            this._handleNetStatusChange
        );
    }

    _handleConnectivityChange = (isConnected) => {
        this.setState({
            isConnected: isConnected
        });
        ToastAndroid.show((isConnected ? 'online' : 'offline'), ToastAndroid.SHORT);
    }

    _handleNetStatusChange = (status) => {
        this.setState({
            connectionInfo: status
        });
        ToastAndroid.show('当然网络状态:' + status, ToastAndroid.SHORT);
    }

    render() {
        return (
            <View >
                <Text style={styles.welcome}>当前的网络状态</Text>
                <Text style={styles.welcome}>{this.state.isConnected ? '网络在线' : '离线'}</Text>
                <Text style={styles.welcome}>当前网络连接类型</Text>
                <Text style={styles.welcome}>{this.state.connectionInfo}</Text>
                <Text style={styles.welcome}>当前网络是否计费(仅Android平台)</Text>
                <Text style={styles.welcome}>{NetInfo.isConnectionExpensive === true ? '需要计费' : '不要计费'}</Text>

                <Text onPress={this.goPostNet1.bind(this) } style={styles.btn}>fetch-POST访问网络1</Text>
                <Text onPress={this.goPostNet2.bind(this) } style={styles.btn}>fetch-POST访问网络2</Text>
                <Text onPress={this.goGetNet.bind(this) } style={[styles.btn, {backgroundColor: 'blue'}]}>fetch-GET访问网络</Text>
            </View>
        );
    }

    goPostNet1() {
        ToastAndroid.show('fetch-POST访问网络-方法1', ToastAndroid.SHORT);
        let url = 'http://www.test.com/login.php';
        let map = { method: 'POST' };

        let privateHeaders = {
            'Private-header1': 'value1',
            'Private-header2': 'value2',
            'Content-Type': 'text/plain',
            'User-Agent': 'testAgent',
        };

        // map.headers = privateHeaders;
        //post的数据 post才需要body
        map.body = JSON.stringify({
            'username': 'test',
            'password': 'test',
            'act': 'signin',
        });

        //如果你的服务器无法识别上面POST的数据格式,那么可以尝试传统的 application/x-www-form-urlencoded 格式
        //map.body = 'username=test&password=test&act=signin';
        map.follow = 10; //设置请求允许的最大重定向次数,0为不允许重定向
        map.timeout = 8000; //设置超时时间,0为没有超时时间,这个值在重定向时会被重置
        map.size = 0; //设置请求回应中的消息体最大允许长度,0为没有限制

        console.log('fetch-POST访问网络-方法1');

        fetch(url, map).then(
            (response) => {
                console.log('fetch-第一个then里面');
                return response.text();
            }
            // (response) => response.text()
        ).then(
            (responseText) => {
                //这里不能使用console否则看不到,这是一个巨大的坑,使用alert一点问题没有
                alert('服务器返回:' + responseText);
                // console.log('服务器返回:' + responseText);
            }
        ).catch(
            (err) => {
                console.log('错误:' + err);
            }
        );
    }

    goPostNet2() {
        ToastAndroid.show('fetch-POST访问网络-方法2', ToastAndroid.SHORT);
        let url = 'http://www.test.com/login.php';
        let data = {
            'username': 'test',
            'password': 'test',
            'act': 'signin',
        };
        console.log('fetch-POST访问网络-方法2');
        this.postRequest(url, data, (result) => {
            alert('服务器返回结果:' + result);
            // console.log('服务器返回结果:' + result);
        });
    }

    postRequest(url, data, callback) {
        let map = {
            method: 'POST',
            headers: {
                'Private-header1': 'value1',
                'Private-header2': 'value2',
                'Content-Type': 'text/plain',
                'User-Agent': 'testAgent',
            },
            body: JSON.stringify(data),
            follow: 20,
            timeout: 8000,
            size: 0,
        };

        fetch(url, map).then((response) => response.text()).then(
            (responseText) => {
                callback(responseText);
            }
        ).catch(
            (err) => {
                callback(err);
            }
        );
    }

    goGetNet() {
        ToastAndroid.show('fetch-GET访问网络', ToastAndroid.SHORT);
        console.log('GET访问网络');
        let url = 'http://www.baidu.com';
        let map = {
            method: 'GET',
            headers: {
                'Accept': 'text/html,application/xhtml+xml,application/xml,application/json,image/webp,*/*;',
                'Content-Type': 'text/plain;charset=UTF-8',
                'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.89 Safari/537.36',
            },
        };
        fetch(url).then(
            (response) => {
                console.log('第一个then里面');
                return response.text()
            }
        ).then(
            (responseText) => {
                //这里不能使用console否则看不到,这是一个巨大的坑,使用alert一点问题没有
                alert('服务器返回:' + responseText);
                // console.log('服务器返回:' + responseText);
            }
        ).catch(
            (err) => {
                console.log('err' + err);
            }
        );
    }
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: '#F5FCFF',
    },
    btn: {
        backgroundColor: '#FF7200',
        height: 33,
        textAlign: 'center',
        textAlignVertical: 'center',
        color: '#fff',
        marginLeft: 10,
        marginRight: 10,
        lineHeight: 24,
        marginTop: 40,
        fontSize: 18,
    },
    welcome: {
        fontSize: 20,
        textAlign: 'center',
        margin: 10,
    },
    instructions: {
        textAlign: 'center',
        color: '#333333',
        marginBottom: 5,
    },
});

AppRegistry.registerComponent('RNAPP', () => RNAPP);

版权声明:
作者:Joe.Ye
链接:https://www.appblog.cn/index.php/2023/02/25/react-native-learning-network-state-and-data-interaction-api/
来源:APP全栈技术分享
文章版权归作者所有,未经允许请勿转载。

THE END
分享
二维码
打赏
海报
React Native学习之网络状态与数据交互API
NetInfo网络连接状态 获取网络状态是异步的,使用js的Promise机制 Android平台的网络连接类型状态如下: 1). NONE:设备没有网络连接 2). BLUETOOTH:蓝牙数……
<<上一篇
下一篇>>
文章目录
关闭
目 录