React Native学习之定时器与手机定位Geolocation API
定时器
定时器API:setTimeout
、setInterval
、setImmediate
、requestAnimationFrame
跟浏览器中的一致
setTimeout
:设置定时任务,隔多久去执行setInterval
:设置循环执行的任务,每隔多久循环执行一次setImmediate
:设置立即执行的任务requestAnimationFrame
:用递归来设置动画;相对setTimeout(fn, 0)
来说,有优势:能够在动画流刷新后执行,即上一个动画流会完整执行。
requestAnimationFrame(fn)
和setTimeout(fn, 0)
不同,前者会在每帧刷新之后执行一次,而后者则会尽可能快的执行(在iPhone5S上有可能每秒1000次以上)。
用js来实现动画,我们一般是借助setTimeout
或setInterval
这两个函数,css3动画出来后,我们又可以使用css3来实现动画,而且性能和流畅度也得到很大的提升。但是css3动画还是有不少局限性,比如不是所有属性都能参与动画、动画缓动效果太少、无法完全控制动画过程等等。所以有的时候我们还是不得不使用setTimeout或setInterval的方式来实现动画,可是setTimeout
和setInterval
有着严重的性能问题,虽然某些现代浏览器对这两函个数进行了一些优化,但还是无法跟css3的动画性能相提并论。这个时候,就可以使用requestAnimationFrame
。requestAnimationFrame
是专门为实现高性能的帧动画而设计的一个API。
setImmediate则会在当前JavaScript执行块结束的时候执行,就在将要发送批量响应数据到原生之前。注意如果你在setImmediate的回调函数中又执行了setImmediate,它会紧接着立刻执行,而不会在调用之前等待原生代码。
Promise的实现就使用了setImmediate来执行异步调用。
TimerMixin
很多React Native应用发生致命错误(闪退)是与计时器有关。具体来说,是在某个组件被卸载(unmount)之后,计时器却仍然被激活。为了解决这个问题,我们引入了TimerMixin
。如果你在组件中引入TimerMixin
,就可以把你原本的setTimeout(fn, 500)
改为this.setTimeout(fn, 500)
(只需要在前面加上this.
),然后当你的组件卸载时,所有的计时器事件也会被正确的清除。
安装组件
npm i react-timer-mixin --save
注意:Mixin属于ES5语法(js的混合封装方法),对于ES6代码来说,无法直接使用Mixin。如果你的项目是用ES6代码编写,同时又使用了计时器,那么你只需铭记在unmount组件时手动清除所有用到的定时器,也可以实现和TimerMixin同样的效果。
monent
使用moment.js
可以实现轻松管理日期和时间(日期和时间格式化)
安装组件
npm i moment --save
取当前时间并格式化
moment().format('YYYY-MM-DD HH:mm:ss')
定位 API
手机定位的API:Geolocation
提供四个静态方法:
getCurrentPosition
watchPosition
clearWacth
stopObserving
Android需要在清单文件(AndroidManifest.xml)中添加权限(需重新编译):
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
IOS需要在Info.plist
中增加NSLocationWhenInUseUsageDescription
字段来启用定位功能。如果你使用react-native init
创建项目,定位会被默认启用。
综合案例
源码:
/**
* Sample React Native App
* https://github.com/facebook/react-native
* @flow
*/
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View
} from 'react-native';
import moment from 'moment';
import Geolocation from 'Geolocation';
let lastTime = 0;
let currentTime = 0;
class RNAPP extends Component {
constructor(props) {
super(props);
this.state = {
width: 0
};
}
render() {
console.log('render');
let css = [];
css.push(styles.progress);
if (this.state.width) {
css.push({ width: this.state.width });
}
return (
<View>
<Text onPress={this._setInterval} style={styles.btn}>setInterval</Text>
<View style={css}></View>
</View>
);
}
_setInterval() {
console.log('获取网页数据 - 当前时间为:' + moment().format('YYYY-MM-DD HH:mm:ss'));
this.interval = setInterval(() => {
fetch('http://www.baidu.com')
.then(function (data) {
return data.text();
})
.then((responseText) => {
console.log('返回数据 - 时间为:' + moment().format('YYYY-MM-DD HH:mm:ss'));
//console.log(responseText);
})
.catch((error) => {
console.warn(error);
});
}, 5000);
}
componentDidMount() {
var _that = this;
//5秒之后取当前手机的位置
alert('开始获取位置信息:' + moment().format('YYYY-MM-DD HH:mm:ss'));
this.timer = setTimeout(() => {
Geolocation.getCurrentPosition((data) => {
//为了看到效果,不要使用console输出,同时记得计时器一定要全部清空,否则会有问题
alert('5秒钟之后得到位置信息:' + JSON.stringify(data) + '当前时间为:' + moment().format('YYYY-MM-DD HH:mm:ss'));
}, (e) => {
alert(JSON.stringify(e));
});
}, 5000);
this.immediate = setImmediate(
() => {
console.log('立刻执行, 当前时间:' + moment().format('YYYY-MM-DD HH:mm:ss'));
}
);
function doAnimated() {
_that.setState({
width: _that.state.width + 10
});
currentTime = new Date().getTime();
console.log('当前的宽度:' + _that.state.width + ', 当前时间:' + currentTime+', 时间间隔:' + (currentTime-lastTime));
console.log('当前的宽度:' + _that.state.width + ', 当前时间:' + moment().format('YYYY-MM-DD HH:mm:ss'));
lastTime = currentTime;
if (_that.state.width < 300) {
requestAnimationFrame(doAnimated);
}
}
requestAnimationFrame(doAnimated);
}
componentWillUnmount() {
//如果存在this.timer,则使用clearTimeout清空。
//如果你使用多个timer,那么用多个变量,或者用个数组来保存引用,然后逐个clear
this.timer && clearTimeout(this.timer);
this.immediate && clearImmediate(this.immediate);
this.interval && clearInterval(this.interval);
console.log('清空所有的计时器');
}
}
const styles = StyleSheet.create({
btn: {
marginTop: 50,
marginLeft: 10,
marginRight: 10,
height: 35,
backgroundColor: '#3BC1FF',
color: '#fff',
lineHeight: 24,
fontWeight: 'bold',
textAlign: 'center',
textAlignVertical:'center'
},
progress: {
height: 10,
width: 10,
marginLeft: 10,
backgroundColor: '#E72D00',
marginTop: 10
},
});
AppRegistry.registerComponent('RNAPP', () => RNAPP);
Console 输出:
render
立刻执行, 当前时间:2016-10-03 09:18:32
render
当前的宽度:10, 当前时间:1475457513386, 时间间隔:1475457513386
当前的宽度:10, 当前时间:2016-10-03 09:18:33
render
当前的宽度:20, 当前时间:1475457513844, 时间间隔:458
当前的宽度:20, 当前时间:2016-10-03 09:18:33
render
当前的宽度:30, 当前时间:1475457514337, 时间间隔:493
当前的宽度:30, 当前时间:2016-10-03 09:18:34
render
当前的宽度:40, 当前时间:1475457514846, 时间间隔:509
当前的宽度:40, 当前时间:2016-10-03 09:18:34
render
当前的宽度:50, 当前时间:1475457515359, 时间间隔:513
当前的宽度:50, 当前时间:2016-10-03 09:18:35
render
当前的宽度:60, 当前时间:1475457515974, 时间间隔:615
当前的宽度:60, 当前时间:2016-10-03 09:18:35
render
当前的宽度:70, 当前时间:1475457516488, 时间间隔:514
当前的宽度:70, 当前时间:2016-10-03 09:18:36
render
当前的宽度:80, 当前时间:1475457516998, 时间间隔:510
当前的宽度:80, 当前时间:2016-10-03 09:18:36
render
当前的宽度:90, 当前时间:1475457517512, 时间间隔:514
当前的宽度:90, 当前时间:2016-10-03 09:18:37
render
当前的宽度:100, 当前时间:1475457517953, 时间间隔:441
当前的宽度:100, 当前时间:2016-10-03 09:18:37
render
当前的宽度:110, 当前时间:1475457518449, 时间间隔:496
当前的宽度:110, 当前时间:2016-10-03 09:18:38
render
当前的宽度:120, 当前时间:1475457518942, 时间间隔:493
当前的宽度:120, 当前时间:2016-10-03 09:18:38
render
当前的宽度:130, 当前时间:1475457519454, 时间间隔:512
当前的宽度:130, 当前时间:2016-10-03 09:18:39
render
当前的宽度:140, 当前时间:1475457519965, 时间间隔:511
当前的宽度:140, 当前时间:2016-10-03 09:18:39
render
当前的宽度:150, 当前时间:1475457520480, 时间间隔:515
当前的宽度:150, 当前时间:2016-10-03 09:18:40
render
当前的宽度:160, 当前时间:1475457520991, 时间间隔:511
当前的宽度:160, 当前时间:2016-10-03 09:18:40
render
当前的宽度:170, 当前时间:1475457521478, 时间间隔:487
当前的宽度:170, 当前时间:2016-10-03 09:18:41
render
当前的宽度:180, 当前时间:1475457522019, 时间间隔:541
当前的宽度:180, 当前时间:2016-10-03 09:18:42
render
当前的宽度:190, 当前时间:1475457522479, 时间间隔:460
当前的宽度:190, 当前时间:2016-10-03 09:18:42
render
当前的宽度:200, 当前时间:1475457522991, 时间间隔:512
当前的宽度:200, 当前时间:2016-10-03 09:18:42
render
当前的宽度:210, 当前时间:1475457523552, 时间间隔:561
当前的宽度:210, 当前时间:2016-10-03 09:18:43
render
当前的宽度:220, 当前时间:1475457524065, 时间间隔:513
当前的宽度:220, 当前时间:2016-10-03 09:18:44
render
当前的宽度:230, 当前时间:1475457524528, 时间间隔:463
当前的宽度:230, 当前时间:2016-10-03 09:18:44
render
当前的宽度:240, 当前时间:1475457525087, 时间间隔:559
当前的宽度:240, 当前时间:2016-10-03 09:18:45
render
当前的宽度:250, 当前时间:1475457525542, 时间间隔:455
当前的宽度:250, 当前时间:2016-10-03 09:18:45
render
当前的宽度:260, 当前时间:1475457526020, 时间间隔:478
当前的宽度:260, 当前时间:2016-10-03 09:18:46
render
当前的宽度:270, 当前时间:1475457526476, 时间间隔:456
当前的宽度:270, 当前时间:2016-10-03 09:18:46
render
当前的宽度:280, 当前时间:1475457527081, 时间间隔:605
当前的宽度:280, 当前时间:2016-10-03 09:18:47
render
当前的宽度:290, 当前时间:1475457527533, 时间间隔:452
当前的宽度:290, 当前时间:2016-10-03 09:18:47
render
当前的宽度:300, 当前时间:1475457528056, 时间间隔:523
当前的宽度:300, 当前时间:2016-10-03 09:18:48
版权声明:
作者:Joe.Ye
链接:https://www.appblog.cn/index.php/2023/02/25/react-native-learning-timer-and-mobile-location-geolocation-api/
来源:APP全栈技术分享
文章版权归作者所有,未经允许请勿转载。
共有 0 条评论