Flutter Geolocator无法多次调用getCurrentPosition()问题
问题原因
你的代码不存在基础语法错误,这个现象是geolocator插件的底层机制导致的:
- 插件和原生系统交互的位置请求通道为单例实现,同一时间只能处理一个当前位置查询请求
- 你在
initState中并发调用两次getCurrentPosition时,后发起的第二个请求会直接覆盖前一个处于挂起状态的请求。被覆盖的第一个请求对应的Future既不会返回成功结果,也不会抛出可捕获的异常,会一直处于等待状态,因此getLocation1中await之后的打印逻辑永远不会执行,只有后发起的getLocation2能正常拿到结果完成打印。
修复方法
不要并发触发getCurrentPosition调用,根据业务场景选以下方案即可:
方案1:缓存请求结果复用
如果同一页面只需要获取一次当前位置,直接把首次请求的结果缓存,后续所有调用直接返回缓存值,避免重复发起原生请求:
Position? _cachedPosition; Future<Position?> getLocation() async { if (_cachedPosition != null) { return _cachedPosition; } try { _cachedPosition = await Geolocator.getCurrentPosition( desiredAccuracy: LocationAccuracy.medium, ); } catch (e) { _cachedPosition = null; } return _cachedPosition; } void getLocation1() async { var location = await getLocation(); print(location); print("First"); } void getLocation2() async { var location = await getLocation(); print(location); print("Second"); } @override void initState() { super.initState(); getLocation1(); getLocation2(); }
这种写法下第一次调用getLocation发起请求后,第二次调用会等待同一个请求结果返回,两个方法都能正常拿到位置打印内容。
方案2:加请求互斥锁
如果业务上需要多次触发位置刷新,添加请求标记做互斥,保证同一时间只有一个位置请求在执行,避免请求被覆盖:
bool _isLocationRequestRunning = false; Future<Position?> getLocation() async { // 存在正在执行的请求时直接返回,也可以根据业务需求改为等待当前请求完成 if (_isLocationRequestRunning) { return null; } Position? currentLocation; try { _isLocationRequestRunning = true; currentLocation = await Geolocator.getCurrentPosition( desiredAccuracy: LocationAccuracy.medium, ); } catch (e) { currentLocation = null; } finally { _isLocationRequestRunning = false; } return currentLocation; }
补充说明:如果需要持续获取位置更新,不要反复调用
getCurrentPosition,直接使用Geolocator.getPositionStream()订阅位置流即可,这是官方推荐的连续位置获取方式,不会出现请求覆盖的问题。
内容的提问来源于stack exchange,提问作者arbis
相关产品推荐
相关产品推荐

