mirror of
https://github.com/dz0ny/meshcore-sar.git
synced 2026-08-11 16:30:28 +00:00
fix: safe scan notifications
ref:
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:flutter/scheduler.dart';
|
||||||
import 'package:flutter_blue_plus/flutter_blue_plus.dart';
|
import 'package:flutter_blue_plus/flutter_blue_plus.dart';
|
||||||
import 'package:crypto/crypto.dart';
|
import 'package:crypto/crypto.dart';
|
||||||
import '../models/device_info.dart';
|
import '../models/device_info.dart';
|
||||||
@@ -461,7 +462,7 @@ class ConnectionProvider with ChangeNotifier {
|
|||||||
_isScanning = true;
|
_isScanning = true;
|
||||||
_scannedDevices.clear();
|
_scannedDevices.clear();
|
||||||
_error = null;
|
_error = null;
|
||||||
notifyListeners();
|
_notifyListenersSafely();
|
||||||
debugPrint('✅ [Provider] Scan state initialized, notifying listeners');
|
debugPrint('✅ [Provider] Scan state initialized, notifying listeners');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -477,7 +478,7 @@ class ConnectionProvider with ChangeNotifier {
|
|||||||
debugPrint(
|
debugPrint(
|
||||||
'✅ [Provider] Added device to list: ${device.platformName} (RSSI: $rssi dBm), total: ${_scannedDevices.length}',
|
'✅ [Provider] Added device to list: ${device.platformName} (RSSI: $rssi dBm), total: ${_scannedDevices.length}',
|
||||||
);
|
);
|
||||||
notifyListeners();
|
_notifyListenersSafely();
|
||||||
} else {
|
} else {
|
||||||
// Update RSSI if device already exists
|
// Update RSSI if device already exists
|
||||||
final index = _scannedDevices.indexWhere(
|
final index = _scannedDevices.indexWhere(
|
||||||
@@ -488,7 +489,7 @@ class ConnectionProvider with ChangeNotifier {
|
|||||||
debugPrint(
|
debugPrint(
|
||||||
' 🔄 [Provider] Updated RSSI for ${device.platformName}: $rssi dBm',
|
' 🔄 [Provider] Updated RSSI for ${device.platformName}: $rssi dBm',
|
||||||
);
|
);
|
||||||
notifyListeners();
|
_notifyListenersSafely();
|
||||||
} else {
|
} else {
|
||||||
debugPrint(
|
debugPrint(
|
||||||
' ⏭️ [Provider] Device already in list with same RSSI, skipping',
|
' ⏭️ [Provider] Device already in list with same RSSI, skipping',
|
||||||
@@ -502,7 +503,7 @@ class ConnectionProvider with ChangeNotifier {
|
|||||||
} finally {
|
} finally {
|
||||||
debugPrint('🏁 [Provider] Scan completed');
|
debugPrint('🏁 [Provider] Scan completed');
|
||||||
_isScanning = false;
|
_isScanning = false;
|
||||||
notifyListeners();
|
_notifyListenersSafely();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -510,6 +511,18 @@ class ConnectionProvider with ChangeNotifier {
|
|||||||
Future<void> stopScan() async {
|
Future<void> stopScan() async {
|
||||||
await FlutterBluePlus.stopScan();
|
await FlutterBluePlus.stopScan();
|
||||||
_isScanning = false;
|
_isScanning = false;
|
||||||
|
_notifyListenersSafely();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _notifyListenersSafely() {
|
||||||
|
final phase = SchedulerBinding.instance.schedulerPhase;
|
||||||
|
if (phase == SchedulerPhase.transientCallbacks ||
|
||||||
|
phase == SchedulerPhase.persistentCallbacks) {
|
||||||
|
SchedulerBinding.instance.addPostFrameCallback((_) {
|
||||||
|
notifyListeners();
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ class ConnectionDialog extends StatefulWidget {
|
|||||||
class _ConnectionDialogState extends State<ConnectionDialog>
|
class _ConnectionDialogState extends State<ConnectionDialog>
|
||||||
with SingleTickerProviderStateMixin {
|
with SingleTickerProviderStateMixin {
|
||||||
late TabController _tabController;
|
late TabController _tabController;
|
||||||
|
late final ConnectionProvider _connectionProvider;
|
||||||
final NetworkScannerService _networkScanner = NetworkScannerService();
|
final NetworkScannerService _networkScanner = NetworkScannerService();
|
||||||
final List<DiscoveredServer> _discoveredServers = [];
|
final List<DiscoveredServer> _discoveredServers = [];
|
||||||
int _scannedCount = 0;
|
int _scannedCount = 0;
|
||||||
@@ -46,16 +47,13 @@ class _ConnectionDialogState extends State<ConnectionDialog>
|
|||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
_tabController = TabController(length: 2, vsync: this);
|
_tabController = TabController(length: 2, vsync: this);
|
||||||
|
_connectionProvider = Provider.of<ConnectionProvider>(context, listen: false);
|
||||||
|
|
||||||
// Defer scan startup until after the first frame so Provider listeners
|
// Defer scan startup until after the first frame so Provider listeners
|
||||||
// are not notified while this dialog is still being built.
|
// are not notified while this dialog is still being built.
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
final connectionProvider = Provider.of<ConnectionProvider>(
|
_connectionProvider.startScan();
|
||||||
context,
|
|
||||||
listen: false,
|
|
||||||
);
|
|
||||||
connectionProvider.startScan();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Set up network scanner callbacks
|
// Set up network scanner callbacks
|
||||||
@@ -85,11 +83,7 @@ class _ConnectionDialogState extends State<ConnectionDialog>
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
final connectionProvider = Provider.of<ConnectionProvider>(
|
_connectionProvider.stopScan();
|
||||||
context,
|
|
||||||
listen: false,
|
|
||||||
);
|
|
||||||
connectionProvider.stopScan();
|
|
||||||
_networkScanner.stopScan();
|
_networkScanner.stopScan();
|
||||||
// Remove listener before disposing to prevent memory leaks
|
// Remove listener before disposing to prevent memory leaks
|
||||||
_tabController.removeListener(_onTabChanged);
|
_tabController.removeListener(_onTabChanged);
|
||||||
|
|||||||
Reference in New Issue
Block a user