Flutter使用Geolocator获取定位时的异常场景处理问题咨询
解决方案
核心修改点
- 拆分定位状态为多类型,区分权限异常、服务异常、加载、成功四类场景
- 修正异步逻辑顺序,先校验权限,再校验定位服务,再执行定位
- 新增定位服务状态监听,用户手动开启服务后自动触发定位刷新
- 完善异常捕获,不同异常对应不同提示文案
完整修改后代码
import 'package:flutter/material.dart'; import 'package:geocoding/geocoding.dart'; import 'package:geolocator/geolocator.dart'; import 'package:location/location.dart' as loc; // 定位状态枚举 enum LocationState { loading, success, permissionDenied, permissionPermanentlyDenied, serviceDisabled } class LocationPage extends StatefulWidget { @override _LocationPageState createState() => _LocationPageState(); } class _LocationPageState extends State<LocationPage> { Position? _currentPosition; String? _currentAddress; LocationState _locationState = LocationState.loading; final loc.Location locationR = loc.Location(); @override void initState() { super.initState(); _initLocation(); // 监听定位服务开关变化 locationR.onServiceChanged.listen((isEnabled) { if (isEnabled) { _checkPermission(); } else { setState(() { _locationState = LocationState.serviceDisabled; }); } }); } Future<void> _initLocation() async { await _checkPermission(); } Future<void> _checkPermission() async { setState(() => _locationState = LocationState.loading); LocationPermission permission = await Geolocator.checkPermission(); // 权限未申请/被拒绝,发起申请 if (permission == LocationPermission.denied) { permission = await Geolocator.requestPermission(); if (permission == LocationPermission.denied) { setState(() => _locationState = LocationState.permissionDenied); return; } } // 权限被永久拒绝 if (permission == LocationPermission.deniedForever) { setState(() => _locationState = LocationState.permissionPermanentlyDenied); return; } // 权限正常,校验定位服务 await _checkLocationService(); } Future<void> _checkLocationService() async { bool serviceEnabled = await Geolocator.isLocationServiceEnabled(); if (!serviceEnabled) { // 申请开启定位服务 bool requestResult = await locationR.requestService(); if (!requestResult) { setState(() => _locationState = LocationState.serviceDisabled); return; } } // 服务正常,获取定位 _getCurrentLocation(); } _getCurrentLocation() { Geolocator.getCurrentPosition( desiredAccuracy: LocationAccuracy.best, forceAndroidLocationManager: true ).then((Position position) { setState(() { _currentPosition = position; }); _getAddressFromLatLng(_currentPosition!); }).catchError((e) { setState(() => _locationState = LocationState.serviceDisabled); }); } _getAddressFromLatLng(Position position) async { try { List<Placemark> placemarks = await placemarkFromCoordinates(position.latitude, position.longitude); Placemark place = placemarks[0]; setState(() { _currentAddress = "${place.locality}, ${place.postalCode}, ${place.country}"; _locationState = LocationState.success; }); } catch (e) { print(e); } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text("Location"), ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ _buildContent(), // 异常场景的操作按钮 if (_locationState == LocationState.permissionPermanentlyDenied) ElevatedButton( onPressed: () => Geolocator.openAppSettings(), child: const Text("去系统设置开启权限"), ), if (_locationState == LocationState.serviceDisabled) ElevatedButton( onPressed: () => _checkLocationService(), child: const Text("开启定位服务"), ), ], ), ), ); } Widget _buildContent() { switch(_locationState) { case LocationState.loading: return const CircularProgressIndicator(); case LocationState.success: return Text(_currentAddress ?? "获取位置成功"); case LocationState.permissionDenied: return const Text("定位权限被拒绝,请授予权限后重试"); case LocationState.permissionPermanentlyDenied: return const Text("定位权限被永久拒绝,请在系统设置中开启"); case LocationState.serviceDisabled: return const Text("定位服务未开启,请开启后重试"); } } }
场景处理说明
- 权限拒绝场景:调用
Geolocator.requestPermission后返回denied状态,对应展示权限拒绝提示 - 服务未开启场景:检测到定位服务关闭时,设置状态为
serviceDisabled,展示对应服务异常提示 - 手动开启服务自动刷新:通过
locationR.onServiceChanged监听服务状态,用户手动开启定位服务后,会自动触发权限校验和定位请求,成功后自动展示地址信息,错误提示消失
内容的提问来源于stack exchange,提问作者GTF
相关产品推荐
相关产品推荐

