React Native学习之定时器与手机定位Geolocation API

定时器

定时器API:setTimeoutsetIntervalsetImmediaterequestAnimationFrame跟浏览器中的一致

  • setTimeout:设置定时任务,隔多久去执行
  • setInterval:设置循环执行的任务,每隔多久循环执行一次
  • setImmediate:设置立即执行的任务
  • requestAnimationFrame:用递归来设置动画;相对setTimeout(fn, 0)来说,有优势:能够在动画流刷新后执行,即上一个动画流会完整执行。

requestAnimationFrame(fn)setTimeout(fn, 0)不同,前者会在每帧刷新之后执行一次,而后者则会尽可能快的执行(在iPhone5S上有可能每秒1000次以上)。

用js来实现动画,我们一般是借助setTimeoutsetInterval这两个函数,css3动画出来后,我们又可以使用css3来实现动画,而且性能和流畅度也得到很大的提升。但是css3动画还是有不少局限性,比如不是所有属性都能参与动画、动画缓动效果太少、无法完全控制动画过程等等。所以有的时候我们还是不得不使用setTimeout或setInterval的方式来实现动画,可是setTimeoutsetInterval有着严重的性能问题,虽然某些现代浏览器对这两函个数进行了一些优化,但还是无法跟css3的动画性能相提并论。这个时候,就可以使用requestAnimationFramerequestAnimationFrame是专门为实现高性能的帧动画而设计的一个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可以实现轻松管理日期和时间(日期和时间格式化)

官网:http://momentjs.com/

安装组件

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

THE END
分享
二维码
打赏
海报
React Native学习之定时器与手机定位Geolocation API
定时器 定时器API:setTimeout、setInterval、setImmediate、requestAnimationFrame跟浏览器中的一致 setTimeout:设置定时任务,隔多久去执行 setInterval……
<<上一篇
下一篇>>
文章目录
关闭
目 录