You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.13 02:06:02