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
相关产品推荐
相关产品推荐

