chore(02-01): add provider dependencies and refactor GpsDataManager
- Added provider ^6.1.2 and shared_preferences ^2.3.4 to pubspec.yaml - Removed singleton pattern from GpsDataManager (deleted _instance and instance getter) - Changed GpsDataManager._internal() to public GpsDataManager() constructor - Extended ChangeNotifier to enable reactive state updates - Added _isDisposed guard field to prevent disposed notifications - Updated _updateData() to call notifyListeners() after stream emission - Added _isDisposed guards to _onGpsError() and _handleStaleDataTimeout() - Updated dispose() to set _isDisposed, call super.dispose() last, removed _isInitialized reset
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import 'dart:async';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:geolocator/geolocator.dart';
|
||||
import '../gps_service.dart';
|
||||
import '../config/speed_unit.dart';
|
||||
@@ -6,11 +7,8 @@ import '../config/gps_constants.dart';
|
||||
import '../models/processed_gps_data.dart';
|
||||
import 'logger.dart';
|
||||
|
||||
class GpsDataManager {
|
||||
static GpsDataManager? _instance;
|
||||
static GpsDataManager get instance => _instance ??= GpsDataManager._internal();
|
||||
|
||||
GpsDataManager._internal();
|
||||
class GpsDataManager extends ChangeNotifier {
|
||||
GpsDataManager();
|
||||
|
||||
StreamSubscription<Position>? _gpsSubscription;
|
||||
final StreamController<ProcessedGpsData> _dataController =
|
||||
@@ -26,6 +24,7 @@ class GpsDataManager {
|
||||
);
|
||||
|
||||
Timer? _staleDataTimer;
|
||||
bool _isDisposed = false;
|
||||
|
||||
// Public stream for UI components to subscribe to
|
||||
Stream<ProcessedGpsData> get dataStream => _dataController.stream;
|
||||
@@ -157,6 +156,7 @@ class GpsDataManager {
|
||||
}
|
||||
|
||||
void _onGpsError(dynamic error) {
|
||||
if (_isDisposed) return;
|
||||
// Handle GPS errors gracefully
|
||||
final errorString = error.toString().toLowerCase();
|
||||
if (!errorString.contains('timeout') && !errorString.contains('temporarily')) {
|
||||
@@ -175,6 +175,7 @@ class GpsDataManager {
|
||||
}
|
||||
|
||||
void _handleStaleDataTimeout() {
|
||||
if (_isDisposed) return;
|
||||
// Avoid overriding explicit GPS error states or repeated stale notifications
|
||||
final displayText = _currentData.displaySpeed;
|
||||
if (displayText == '--' || displayText.startsWith('GPS') || displayText == 'NO PERM') {
|
||||
@@ -198,9 +199,11 @@ class GpsDataManager {
|
||||
}
|
||||
|
||||
void _updateData(ProcessedGpsData newData) {
|
||||
if (_isDisposed) return;
|
||||
Logger.debug('Broadcasting data: ${newData.displaySpeed} ${newData.displayHeading}', 'GpsDataManager');
|
||||
_currentData = newData;
|
||||
_dataController.add(newData);
|
||||
notifyListeners();
|
||||
Logger.debug('Data broadcast complete', 'GpsDataManager');
|
||||
}
|
||||
|
||||
@@ -212,7 +215,9 @@ class GpsDataManager {
|
||||
return convertedSpeed < 1.0 ? '--' : convertedSpeed.toStringAsFixed(1);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_isDisposed = true;
|
||||
Logger.info('Disposing GPS manager...', 'GpsDataManager');
|
||||
if (_gpsSubscription != null) {
|
||||
Logger.debug('Cancelling GPS subscription...', 'GpsDataManager');
|
||||
@@ -223,7 +228,7 @@ class GpsDataManager {
|
||||
_staleDataTimer?.cancel();
|
||||
_staleDataTimer = null;
|
||||
_dataController.close();
|
||||
_isInitialized = false;
|
||||
Logger.info('GPS manager disposed', 'GpsDataManager');
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,12 @@ dependencies:
|
||||
# Bring app to foreground from background/overlay
|
||||
bg_launcher: ^0.1.0
|
||||
|
||||
# State management
|
||||
provider: ^6.1.2
|
||||
|
||||
# Persistent settings storage
|
||||
shared_preferences: ^2.3.4
|
||||
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
||||
Reference in New Issue
Block a user