react-native - Expo Location问题:watchPositionAsync不返回值或长时间(甚至10分钟)返回
问题描述
晚上好,我正在为业余爱好开发我的第一个 React Native Expo 应用程序。这是一个使用手机地理定位来跟踪用户移动的应用程序,以便在城市中组织寻宝活动。但是我遇到了一个问题:watchPositionAsync 函数的工作非常不稳定。有时位置对象的值会立即返回。但大多数时候,它根本不会被退回,甚至需要 10 分钟才能完成。
这是代码的第一个版本,仅包含有问题的函数:
import React, {useState, useEffect} from 'react';
import * as Location from 'expo-location';
const Navigator = () => {
const [deviceLocation, setDeviceLocation] = useState(null);
const [errorMsg, setErrorMsg] = useState(null);
const getLocationAsync = async() => {
let loc = await Location.watchPositionAsync({
accuracy: Location.Accuracy.BestForNavigation,
timeInterval: 10000,
distanceInterval : 20
},
(newLocation) => {
setDeviceLocation(newLocation);
}
);
};
getLocationAsync()
useEffect(() => {
(async () => {
let { status } = await Location.requestForegroundPermissionsAsync();
if (status !== 'granted') {
setErrorMsg('Permission to access location was denied');
return;
}
})();
}, []);
let text = 'Waiting..';
if (errorMsg) {
text = errorMsg;
} else if (deviceLocation.location !== '') {
text = JSON.stringify(deviceLocation.location);
}
return (
<View>
<Text>{text}</Text>
</View>
)
}
这是具有附加功能的版本(例如在每次重新渲染 watchPositionAsync 函数时计算与预定点的距离,并设置要传达给用户的特定句子):
import React, {useState, useEffect} from 'react';
import NavigatorUI from './NavigatorUI';
import * as Location from 'expo-location';
import { getDistance, findNearest } from 'geolib';
const treasureLocation = {
latitude: 39.2695552,
longitude: 8.4679172
}
const Navigator = () => {
const [deviceLocation, setDeviceLocation] = useState({
location : '',
treasureDist : '',
sentence: ''
});
const [errorMsg, setErrorMsg] = useState(null);
const getLocationAsync = async() => {
let loc = await Location.watchPositionAsync({
accuracy: Location.Accuracy.BestForNavigation,
timeInterval: 10000,
distanceInterval : 20
},
(newLocation) => {
setDeviceLocation({...deviceLocation, location: newLocation});
getDistfromTreasure();
switchDist();
console.warn(deviceLocation.sentence)
}
);
};
getLocationAsync()
const getDistfromTreasure = () => {
if(deviceLocation.location){
let {latitude: deviceLat, longitude: deviceLong} = deviceLocation.location.coords;
let {latitude: treasureLat, longitude: treasureLong} = treasureLocation;
let dist = getDistance({
latitude: deviceLat,
longitude: deviceLong
},
{
latitude: treasureLat,
longitude: treasureLong
}
);
setDeviceLocation({...deviceLocation, treasureDist: dist})
}
};
const switchDist = () =>{
if(deviceLocation.treasureDist){
let {treasureDist: val} = deviceLocation;
if(val > 1000){
setDeviceLocation({...deviceLocation, sentence: 'Example1'});
}
else if(val < 1000 && val > 500){
setDeviceLocation({...deviceLocation, sentence: 'Example2'});
}
else if(val < 500 && val > 100){
setDeviceLocation({...deviceLocation, sentence: 'Example3'});
}
else if(val < 100 && val > 50){
setDeviceLocation({...deviceLocation, sentence: 'Example4'});
}
else if(val < 50){
setDeviceLocation({...deviceLocation, sentence: 'Example5'});
}
}
}
useEffect(() => {
(async () => {
let { status } = await Location.requestForegroundPermissionsAsync();
if (status !== 'granted') {
setErrorMsg('Permission to access location was denied');
return;
}
})();
}, []);
let text = 'Waiting..';
if (errorMsg) {
text = errorMsg;
} else if (deviceLocation.location !== '') {
text = JSON.stringify(deviceLocation.location);
}
return (
<>
<View>
<Text>{text}</Text>
</View>
<View>
<Text>{sentence}</Text>
</View>
</>
)
}
export default Navigator
在这两种情况下,屏幕都会无限期地显示“等待”这个词。另外,在第二种情况下,我注意到重新渲染的发生速度比我使用 timeInterval 选项设置的快得多或慢得多。在任何情况下都具有不连续的速度。
有没有人遇到同样的问题并设法解决它?
解决方案
代码对我来说似乎几乎没问题。我认为在您发布的第一个代码中,如果在渲染之前,最后一个 else 中存在错误。expo 给出的位置对象包含一个属性 coords,如果在读取之前定义了 deviceLocation,您需要检查它。
else if (deviceLocation.location !== '') {
text = JSON.stringify(deviceLocation.location);}
->
else if (deviceLocation && deviceLocation.coords) {
text = JSON.stringify(deviceLocation.coords)};
我也玩了一点代码,我会把它写成:
const Navigator = () => {
console.log('render')
const [permissionResult, setPermissionResult] = useState(undefined);
const [deviceLocation, setDeviceLocation] = useState(null);
const [errorMsg, setErrorMsg] = useState(null);
const getPermissionAsync = async () => {
let { status } = await Location.requestForegroundPermissionsAsync();
setPermissionResult(status)
if (status !== 'granted') {
setErrorMsg('Permission to access location was denied');
return;
}
}
const getLocationAsync = async() => {
await Location.watchPositionAsync({
accuracy: Location.Accuracy.BestForNavigation,
timeInterval: 10000,
distanceInterval : 20
},
(newLocation) => {
setDeviceLocation(newLocation);
}
);
};
useEffect(() => {
// If permission request is not done
if (permissionResult === undefined) {
getPermissionAsync();
}
}, [permissionResult]);
useEffect(()=>{
// If permission has been done and the result is available
if (permissionResult !== undefined) {
getLocationAsync()
}
}, [permissionResult])
let text = 'Waiting..';
if (errorMsg) {
console.log('errore')
text = errorMsg;
} else if (deviceLocation && deviceLocation.coords) {
text = JSON.stringify(deviceLocation.coords);
console.log(deviceLocation)
}
return (
<View>
<Text>{text}</Text>
</View>
)
}
我希望这会有所帮助,并且我理解这个问题
推荐阅读
- objective-c - 我应该如何查询 Retina 硬件中的物理像素数?
- excel - 大于 0 的前 4 个数字的平均值 Microsoft Excel
- python - 在 Python 中进行优化的冒泡排序
- gulp - Gulp 4 手表 gulp.series 只运行一次
- javascript - url中的角度路由更改
- objective-c - 如何用objective c显示多张导入的照片
- angular - 如何在 Angular.io 中通过单击按钮更改输入值并触发输入事件
- javascript - 为什么每次我开始我的功能我都会得到 NaN
- python-3.x - 使用python3修改数据及其格式
- wpf - SignalR Owin 日志记录