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

Flutter返回页面后Location Services无法自动更新问题求助

解决定位服务开启后页面不自动更新的问题

你的问题核心在于:当用户从设置页开启定位服务返回后,代码没有重新触发定位获取流程。当前逻辑仅在页面初始化时执行一次_determinePosition(),但从设置返回后未重新检查服务状态或发起定位请求,导致位置信息无法自动更新。

以下是具体解决方案:

1. 监听定位服务状态变化

利用Geolocator提供的服务状态流,实时监听定位服务的开启/关闭状态,当服务从关闭变为开启时自动重新获取定位信息。

修改onInit方法添加状态监听:

@override
void onInit() {
  super.onInit();
  // 监听定位服务状态变化
  streamSubscriptionServiceStatus = Geolocator.getServiceStatusStream().listen((ServiceStatus status) {
    if (status == ServiceStatus.enabled) {
      _determinePosition();
    }
  });
  _determinePosition();
}

同时在onClose中取消订阅避免内存泄漏:

@override
void onClose() {
  streamSubscription?.cancel();
  streamSubscriptionServiceStatus?.cancel();
  super.onClose();
}

2. 从设置页返回后立即重新检查

修改对话框确认按钮逻辑,在用户从设置页返回后,主动检查定位服务状态并重新发起请求:

confirm: ElevatedButton(
  onPressed: () async {
    await Geolocator.openLocationSettings();
    Get.back();
    // 返回后重新检查服务状态
    bool enabled = await Geolocator.isLocationServiceEnabled();
    if (enabled) {
      _determinePosition();
    }
  },
  child: Text('Confirm')),

3. 优化定位流订阅逻辑

避免重复创建位置流订阅,在每次调用_determinePosition()前取消旧订阅:

// 取消旧订阅,避免重复监听
await streamSubscription?.cancel();
streamSubscription = Geolocator.getPositionStream().listen((Position position) {
  latitude.value = 'Latitude: ${position.latitude}';
  longitude.value = 'Longtitude: ${position.longitude}';
  getAddressFromLatLang(position);
});

完整修改后的代码

import 'dart:async';

import 'package:get/get.dart';
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import '../../../services/screenadapter.dart';
import 'package:geolocator/geolocator.dart';
import 'package:geocoding/geocoding.dart';

class HomeController extends GetxController {
  var latitude = 'Getting Latitude..'.obs;
  var longitude = 'Getting Longtitude..'.obs;
  var address = 'Getting Address..'.obs;
  StreamSubscription<Position>? streamSubscription;
  StreamSubscription<ServiceStatus>? streamSubscriptionServiceStatus;
  late LocationSettings locationSettings;

  _determinePosition() async {
    bool serviceEnabled;
    LocationPermission permission;

    serviceEnabled = await Geolocator.isLocationServiceEnabled();
    if (!serviceEnabled) {
      return Get.defaultDialog(
          title: 'Location Services Disabled',
          middleText: 'You need to enable Location Services in Setting',
          confirm: ElevatedButton(
              onPressed: () async {
                await Geolocator.openLocationSettings();
                Get.back();
                // 返回后重新检查服务状态
                bool enabled = await Geolocator.isLocationServiceEnabled();
                if (enabled) {
                  _determinePosition();
                }
              },
              child: Text('Confirm')),
          cancel: ElevatedButton(
              onPressed: () {
                Get.back();
              },
              child: Text('Cancel')));
    }

    permission = await Geolocator.checkPermission();
    if (permission == LocationPermission.denied) {
      permission = await Geolocator.requestPermission();
      if (permission == LocationPermission.denied) {
        return Future.error('Location permissions are denied');
      }
    }

    if (permission == LocationPermission.deniedForever) {
      return Future.error(
          'Location permissions are permanently denied, we cannot request permissions.');
    }

    // 取消旧订阅,避免重复监听
    await streamSubscription?.cancel();
    streamSubscription =
        Geolocator.getPositionStream().listen((Position position) {
      latitude.value = 'Latitude: ${position.latitude}';
      longitude.value = 'Longtitude: ${position.longitude}';
      getAddressFromLatLang(position);
    });

    return await Geolocator.getCurrentPosition(
        forceAndroidLocationManager: true,
        desiredAccuracy: LocationAccuracy.best);
  }

  Future<void> getAddressFromLatLang(Position position) async {
    List<Placemark> placemark =
        await placemarkFromCoordinates(position.latitude, position.longitude);
    Placemark place = placemark[0];
    address.value = 'GPS: ${place.name},${place.subLocality},${place.locality}';
  }

  RxList itemList = [
    {
      "id": 1,
      "name": "Great Nature Vegetarian",
      "image": "images/greatnature.jpg",
      "Hours": "9am - 10pm",
      "quality": "good",
    },
    {
      "id": 2,
      "name": "Nature Vegan",
      "image": "images/naturevegan.jpg",
      "Hours": "8.30am - 10pm",
      "quality": "good",
    },
    {
      "id": 3,
      "name": "Love Vege Vegetarian",
      "image": "images/lovevege.jpg",
      "Hours": "9am - 8pm",
      "quality": "good",
    },
    {
      "id": 4,
      "name": "Namasthe Vegetarian",
      "image": "images/namasthe.jpg",
      "Hours": "9am - 8.30am",
      "quality": "good",
    },
    {
      "id": 5,
      "name": "Organic Vegetarian Fresh Mart",
      "image": "images/organic.jpg",
      "Hours": "8am - 9.30am",
      "quality": "good",
    },
    {
      "id": 6,
      "name": "Sweet Garden Vegetarian",
      "image": "images/sweetgarden.jpg",
      "Hours": "9.10am - 10pm",
      "quality": "good",
    },
    {
      "id": 7,
      "name": "Tian Xin Vegetarian",
      "image": "images/tianxin.jpg",
      "Hours": "9am - 10pm",
      "quality": "good",
    },
  ].obs;

  Row headerBottomBarWidget() {
    return Row(
      mainAxisSize: MainAxisSize.max,
      mainAxisAlignment: MainAxisAlignment.end,
      crossAxisAlignment: CrossAxisAlignment.center,
      children: [
        GestureDetector(
          onTap: (() {
            Get.toNamed('/search');
          }),
          child: Icon(Icons.search, color: Colors.white),
        )
      ],
    );
  }

  Widget headerWidget(BuildContext context) {
    return SizedBox(
      child: Padding(
        padding: const EdgeInsets.all(8.0),
        child: Column(
          mainAxisSize: MainAxisSize.min,
          crossAxisAlignment: CrossAxisAlignment.start,
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text(
              "Good Day",
              style: GoogleFonts.notoSansJavanese(
                  fontSize: ScreenAdapter.fontSize(150),
                  fontWeight: FontWeight.w700,
                  color: Colors.white),
            ),
            SizedBox(
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Text("Welcome back!",
                      style: GoogleFonts.notoSansJavanese(
                          fontSize: ScreenAdapter.fontSize(85),
                          fontWeight: FontWeight.w700,
                          color: Colors.white)),
                  Obx((() => Text(address.value,
                      overflow: TextOverflow.ellipsis,
                      style: GoogleFonts.notoSansJavanese(
                          fontSize: ScreenAdapter.fontSize(40),
                          fontWeight: FontWeight.w700,
                          color: Colors.white))))
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }

  ListView listView() {
    return ListView.builder(
      padding: const EdgeInsets.only(top: 0),
      physics: const NeverScrollableScrollPhysics(),
      itemCount: itemList.length,
      shrinkWrap: true,
      itemBuilder: (context, index) => Padding(
        padding: EdgeInsets.fromLTRB(ScreenAdapter.width(8), 0,
            ScreenAdapter.width(8), ScreenAdapter.width(15)),
        child: Container(
          width: ScreenAdapter.width(1080),
          height: ScreenAdapter.height(300),
          decoration: const BoxDecoration(
              color: Color.fromARGB(184, 252, 249, 249),
              borderRadius: BorderRadius.all(Radius.circular(10.0)),
              boxShadow: [
                BoxShadow(
                    color: Colors.white,
                    offset: Offset(1.0, 5.0),
                    blurRadius: 10.0,
                    spreadRadius: 2.0)
              ]),
          child: Row(
            children: [
              Container(
                width: ScreenAdapter.width(380),
                decoration: BoxDecoration(
                    borderRadius: const BorderRadius.only(
                        topLeft: Radius.circular(10.0),
                        bottomLeft: Radius.circular(10.0)),
                    image: DecorationImage(
                        image: AssetImage("${itemList[index]['image']}"),
                        fit: BoxFit.cover)),
              ),
              Expanded(
                  child: Container(
                padding: EdgeInsets.fromLTRB(
                    ScreenAdapter.width(8), 0, ScreenAdapter.width(8), 0),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  mainAxisAlignment: MainAxisAlignment.spaceAround,
                  children: [
                    Row(
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      children: [
                        Text("${itemList[index]['name']}"),
                        const Icon(
                          Icons.arrow_forward_ios_outlined,
                          size: 13.0,
                        )
                      ],
                    ),
                    Text("${itemList[index]['Hours']}"),
                    const Icon(Icons.star_border_outlined)
                  ],
                ),
              ))
            ],
          ),
        ),
      ),
    );
  }

  @override
  void onInit() {
    super.onInit();
    // 监听定位服务状态变化
    streamSubscriptionServiceStatus = Geolocator.getServiceStatusStream().listen((ServiceStatus status) {
      if (status == ServiceStatus.enabled) {
        _determinePosition();
      }
    });
    _determinePosition();
  }

  @override
  void onClose() {
    streamSubscription?.cancel();
    streamSubscriptionServiceStatus?.cancel();
    super.onClose();
  }
}

内容的提问来源于stack exchange,提问作者jordan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 05:08:14