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

Flutter中如何停止定时器?定位追踪无法停止问题求助

解决定时定位无法停止的问题

你的核心问题大概率是创建了多个GpsService实例——启动跟踪时用的是一个实例,停止时调用的是另一个全新的实例,导致stopTracking里的zamanlayici永远是null,而真正在运行定时器的那个实例根本没被操作到。

解决方案1:把GpsService改成单例模式

确保整个App里只有一个GpsService实例,启动和停止都操作同一个对象:

class GpsService {
  // 单例实现:全局唯一实例
  static final GpsService _instance = GpsService._internal();
  factory GpsService() => _instance;
  GpsService._internal();

  Timer? zamanlayici;

  Future<void> startTracking(String reportId) async {
    // 先检查是否已有活跃定时器,避免重复启动
    if (zamanlayici?.isActive ?? false) {
      print('定时器已在运行,无需重复启动');
      return;
    }

    bool serviceEnabled;
    LocationPermission permission;
    // 补充你的权限检查逻辑(原代码中声明但未实现)

    zamanlayici = Timer.periodic(Duration(seconds: 10), (timer) async {
      await _updateFirebase(reportId);
    });
    print('Zamanlayıcı başlatıldı.');
  }

  Future<void> _updateFirebase(String reportId) async {
    try {
      Position position = await Geolocator.getCurrentPosition();

      FirebaseFirestore.instance
          .collection('Reports')
          .doc(reportId)
          .collection('Coordinates')
          .doc('last_location')
          .set({
        'latitude': position.latitude,
        'longitude': position.longitude,
        'timestamp': FieldValue.serverTimestamp(),
      }, SetOptions(merge: true));

      print('📌 Firebase\'e konum güncellendi: ${position.latitude}, ${position.longitude}');
    } catch (e) {
      print('Konum alınamadı: $e');
    }
  }

  void stopTracking() {
    if (zamanlayici != null) {
      zamanlayici!.cancel();
      zamanlayici = null;
      print('Takip durduruldu.');
    } else {
      print('Takip zaten durdurulmuş.');
    }
  }
}

调用时统一用单例:

// 启动跟踪
await GpsService().startTracking('你的reportId');
// 停止跟踪
GpsService().stopTracking();

解决方案2:改用Geolocator的位置流(更高效)

之前用getPositionStream遇到的停止问题,大概率也是实例不统一导致的。用流替代Timer更符合定位场景的设计,也能避免Timer的一些坑:

class GpsService {
  static final GpsService _instance = GpsService._internal();
  factory GpsService() => _instance;
  GpsService._internal();

  StreamSubscription<Position>? _positionSubscription;

  Future<void> startTracking(String reportId) async {
    if (_positionSubscription != null) {
      print('定位流已在运行');
      return;
    }

    bool serviceEnabled;
    LocationPermission permission;
    // 补充权限检查逻辑

    _positionSubscription = Geolocator.getPositionStream(
      locationSettings: LocationSettings(
        accuracy: LocationAccuracy.high,
        distanceFilter: 0, // 忽略移动距离,定时更新
        timeInterval: 10000, // 10秒更新一次
      ),
    ).listen((Position position) {
      _updateFirebase(reportId, position);
    });
    print('定位跟踪已启动');
  }

  Future<void> _updateFirebase(String reportId, Position position) async {
    try {
      await FirebaseFirestore.instance
          .collection('Reports')
          .doc(reportId)
          .collection('Coordinates')
          .doc('last_location')
          .set({
        'latitude': position.latitude,
        'longitude': position.longitude,
        'timestamp': FieldValue.serverTimestamp(),
      }, SetOptions(merge: true));

      print('📌 Firebase\'e konum güncellendi: ${position.latitude}, ${position.longitude}');
    } catch (e) {
      print('Konum alınamadı: $e');
    }
  }

  void stopTracking() {
    _positionSubscription?.cancel();
    _positionSubscription = null;
    print('Takip durduruldu.');
  }
}

关键提醒

  • 永远确保启动和停止操作的是同一个GpsService实例,这是解决你当前问题的核心。
  • 启动前检查是否已有活跃的定时器/流,避免重复创建导致资源泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 07:38:11