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=val2multipart/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全栈技术分享
文章版权归作者所有,未经允许请勿转载。
共有 0 条评论