fix: lifecycle
This commit is contained in:
@ -66,15 +66,21 @@ class _BootloaderRecoveryUpdatePageState
|
|||||||
unawaited(_firmwareProgressSubscription?.cancel());
|
unawaited(_firmwareProgressSubscription?.cancel());
|
||||||
unawaited(() async {
|
unawaited(() async {
|
||||||
await service?.dispose();
|
await service?.dispose();
|
||||||
await _disconnectBootloaderIfStillConnected(bluetooth: bluetooth);
|
await _disconnectBootloaderIfStillConnected(
|
||||||
|
bluetooth: bluetooth,
|
||||||
|
allowRefRead: false,
|
||||||
|
);
|
||||||
}());
|
}());
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _disconnectBootloaderIfStillConnected({
|
Future<void> _disconnectBootloaderIfStillConnected({
|
||||||
BluetoothController? bluetooth,
|
BluetoothController? bluetooth,
|
||||||
|
bool allowRefRead = true,
|
||||||
}) async {
|
}) async {
|
||||||
bluetooth ??= ref.read(bluetoothProvider).valueOrNull;
|
if (bluetooth == null && allowRefRead) {
|
||||||
|
bluetooth = ref.read(bluetoothProvider).valueOrNull;
|
||||||
|
}
|
||||||
if (bluetooth == null) {
|
if (bluetooth == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -66,6 +66,7 @@ class _DeviceDetailsPageState extends ConsumerState<DeviceDetailsPage> {
|
|||||||
bool _isPairingCheckRunning = false;
|
bool _isPairingCheckRunning = false;
|
||||||
ProviderSubscription<AsyncValue<(ConnectionStatus, String?)>>?
|
ProviderSubscription<AsyncValue<(ConnectionStatus, String?)>>?
|
||||||
_connectionStatusSubscription;
|
_connectionStatusSubscription;
|
||||||
|
BluetoothController? _bluetooth;
|
||||||
|
|
||||||
ShifterService? _shifterService;
|
ShifterService? _shifterService;
|
||||||
StreamSubscription<CentralStatus>? _statusSubscription;
|
StreamSubscription<CentralStatus>? _statusSubscription;
|
||||||
@ -146,7 +147,10 @@ class _DeviceDetailsPageState extends ConsumerState<DeviceDetailsPage> {
|
|||||||
'Disposing device details page for ${widget.deviceAddress}; '
|
'Disposing device details page for ${widget.deviceAddress}; '
|
||||||
'dfuState=${_dfuProgress.state}, isFirmwareUpdateBusy=$_isFirmwareUpdateBusy',
|
'dfuState=${_dfuProgress.state}, isFirmwareUpdateBusy=$_isFirmwareUpdateBusy',
|
||||||
);
|
);
|
||||||
unawaited(_disconnectOnClose());
|
final bluetooth = _bluetooth;
|
||||||
|
unawaited(
|
||||||
|
_disconnectOnClose(bluetooth: bluetooth, allowRefRead: false),
|
||||||
|
);
|
||||||
_connectionStatusSubscription?.close();
|
_connectionStatusSubscription?.close();
|
||||||
_statusSubscription?.cancel();
|
_statusSubscription?.cancel();
|
||||||
_shifterService?.dispose();
|
_shifterService?.dispose();
|
||||||
@ -155,7 +159,10 @@ class _DeviceDetailsPageState extends ConsumerState<DeviceDetailsPage> {
|
|||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _disconnectOnClose() async {
|
Future<void> _disconnectOnClose({
|
||||||
|
BluetoothController? bluetooth,
|
||||||
|
bool allowRefRead = true,
|
||||||
|
}) async {
|
||||||
if (_isFirmwareUpdateBusy) {
|
if (_isFirmwareUpdateBusy) {
|
||||||
_log.info('Skipping disconnect on close because firmware update is busy');
|
_log.info('Skipping disconnect on close because firmware update is busy');
|
||||||
return;
|
return;
|
||||||
@ -169,10 +176,16 @@ class _DeviceDetailsPageState extends ConsumerState<DeviceDetailsPage> {
|
|||||||
_hasRequestedDisconnect = true;
|
_hasRequestedDisconnect = true;
|
||||||
_isExitingPage = true;
|
_isExitingPage = true;
|
||||||
|
|
||||||
|
final bluetoothController = bluetooth ??
|
||||||
|
_bluetooth ??
|
||||||
|
(allowRefRead ? ref.read(bluetoothProvider).value : null);
|
||||||
|
if (bluetoothController != null) {
|
||||||
|
_bluetooth = bluetoothController;
|
||||||
|
}
|
||||||
|
|
||||||
await _disposeFirmwareUpdateService();
|
await _disposeFirmwareUpdateService();
|
||||||
|
|
||||||
final bluetooth = ref.read(bluetoothProvider).value;
|
await bluetoothController?.disconnect();
|
||||||
await bluetooth?.disconnect();
|
|
||||||
await _stopStatusStreaming();
|
await _stopStatusStreaming();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,6 +224,9 @@ class _DeviceDetailsPageState extends ConsumerState<DeviceDetailsPage> {
|
|||||||
|
|
||||||
if (_shifterService != null) {
|
if (_shifterService != null) {
|
||||||
final bluetooth = ref.read(bluetoothProvider).value;
|
final bluetooth = ref.read(bluetoothProvider).value;
|
||||||
|
if (bluetooth != null) {
|
||||||
|
_bluetooth = bluetooth;
|
||||||
|
}
|
||||||
if (bluetooth == null || !isCurrentDeviceConnected(bluetooth)) {
|
if (bluetooth == null || !isCurrentDeviceConnected(bluetooth)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -239,6 +255,7 @@ class _DeviceDetailsPageState extends ConsumerState<DeviceDetailsPage> {
|
|||||||
} else {
|
} else {
|
||||||
bluetooth = await ref.read(bluetoothProvider.future);
|
bluetooth = await ref.read(bluetoothProvider.future);
|
||||||
}
|
}
|
||||||
|
_bluetooth = bluetooth;
|
||||||
if (!isCurrentDeviceConnected(bluetooth)) {
|
if (!isCurrentDeviceConnected(bluetooth)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -264,6 +281,9 @@ class _DeviceDetailsPageState extends ConsumerState<DeviceDetailsPage> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final bluetooth = ref.read(bluetoothProvider).value;
|
final bluetooth = ref.read(bluetoothProvider).value;
|
||||||
|
if (bluetooth != null) {
|
||||||
|
_bluetooth = bluetooth;
|
||||||
|
}
|
||||||
if (bluetooth == null || !isCurrentDeviceConnected(bluetooth)) {
|
if (bluetooth == null || !isCurrentDeviceConnected(bluetooth)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -523,6 +543,7 @@ class _DeviceDetailsPageState extends ConsumerState<DeviceDetailsPage> {
|
|||||||
if (bluetooth == null) {
|
if (bluetooth == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
_bluetooth = bluetooth;
|
||||||
|
|
||||||
final service = FirmwareUpdateService(
|
final service = FirmwareUpdateService(
|
||||||
transport: ShifterFirmwareUpdateTransport(
|
transport: ShifterFirmwareUpdateTransport(
|
||||||
@ -722,6 +743,7 @@ class _DeviceDetailsPageState extends ConsumerState<DeviceDetailsPage> {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
final bluetooth = await ref.read(bluetoothProvider.future);
|
final bluetooth = await ref.read(bluetoothProvider.future);
|
||||||
|
_bluetooth = bluetooth;
|
||||||
final result = await bluetooth.connectById(
|
final result = await bluetooth.connectById(
|
||||||
widget.deviceAddress,
|
widget.deviceAddress,
|
||||||
timeout: const Duration(seconds: 10),
|
timeout: const Duration(seconds: 10),
|
||||||
|
|||||||
@ -26,8 +26,10 @@ class _DevicesTabPageState extends ConsumerState<DevicesTabPage> {
|
|||||||
static const Duration _bootloaderScanTimeout = Duration(seconds: 10);
|
static const Duration _bootloaderScanTimeout = Duration(seconds: 10);
|
||||||
|
|
||||||
StreamSubscription<List<DiscoveredDevice>>? _scanSubscription;
|
StreamSubscription<List<DiscoveredDevice>>? _scanSubscription;
|
||||||
|
BluetoothController? _bluetooth;
|
||||||
DiscoveredDevice? _dfuDevice;
|
DiscoveredDevice? _dfuDevice;
|
||||||
bool _isBootloaderScanStarting = false;
|
bool _isBootloaderScanStarting = false;
|
||||||
|
bool _isDisposed = false;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
@ -37,8 +39,8 @@ class _DevicesTabPageState extends ConsumerState<DevicesTabPage> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
final bluetooth = ref.read(bluetoothProvider).valueOrNull;
|
_isDisposed = true;
|
||||||
unawaited(_scanSubscription?.cancel());
|
final bluetooth = _bluetooth;
|
||||||
unawaited(_stopBootloaderScan(bluetooth));
|
unawaited(_stopBootloaderScan(bluetooth));
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
@ -52,14 +54,19 @@ class _DevicesTabPageState extends ConsumerState<DevicesTabPage> {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
final bluetooth = await ref.read(bluetoothProvider.future);
|
final bluetooth = await ref.read(bluetoothProvider.future);
|
||||||
if (!mounted) {
|
if (!mounted || _isDisposed) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
_bluetooth = bluetooth;
|
||||||
|
|
||||||
final scanResult = await bluetooth.startScan(
|
final scanResult = await bluetooth.startScan(
|
||||||
timeout: _bootloaderScanTimeout,
|
timeout: _bootloaderScanTimeout,
|
||||||
scanMode: ScanMode.lowLatency,
|
scanMode: ScanMode.lowLatency,
|
||||||
);
|
);
|
||||||
|
if (!mounted || _isDisposed) {
|
||||||
|
await bluetooth.stopScan();
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (scanResult.isErr()) {
|
if (scanResult.isErr()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -74,20 +81,22 @@ class _DevicesTabPageState extends ConsumerState<DevicesTabPage> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _stopBootloaderScan([BluetoothController? bluetooth]) async {
|
Future<void> _stopBootloaderScan([BluetoothController? bluetooth]) async {
|
||||||
await _scanSubscription?.cancel();
|
final subscription = _scanSubscription;
|
||||||
_scanSubscription = null;
|
_scanSubscription = null;
|
||||||
|
await subscription?.cancel();
|
||||||
|
|
||||||
await bluetooth?.stopScan();
|
await bluetooth?.stopScan();
|
||||||
}
|
}
|
||||||
|
|
||||||
void _updateBootloaderDevice(List<DiscoveredDevice> devices) {
|
void _updateBootloaderDevice(List<DiscoveredDevice> devices) {
|
||||||
|
if (_isDisposed || !mounted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
final dfuDevice = devices.cast<DiscoveredDevice?>().firstWhere(
|
final dfuDevice = devices.cast<DiscoveredDevice?>().firstWhere(
|
||||||
(device) => device != null && _isBootloaderAdvertisement(device),
|
(device) => device != null && _isBootloaderAdvertisement(device),
|
||||||
orElse: () => null,
|
orElse: () => null,
|
||||||
);
|
);
|
||||||
if (!mounted) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dfuDevice == null) {
|
if (dfuDevice == null) {
|
||||||
_clearBootloaderDevice();
|
_clearBootloaderDevice();
|
||||||
@ -104,7 +113,7 @@ class _DevicesTabPageState extends ConsumerState<DevicesTabPage> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _clearBootloaderDevice() {
|
void _clearBootloaderDevice() {
|
||||||
if (!mounted || _dfuDevice == null) {
|
if (_isDisposed || !mounted || _dfuDevice == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,12 +148,12 @@ class _DevicesTabPageState extends ConsumerState<DevicesTabPage> {
|
|||||||
builder: (_) => _BootloaderRecoverySetupPage(device: device),
|
builder: (_) => _BootloaderRecoverySetupPage(device: device),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
if (!mounted || firmware == null) {
|
if (!mounted || _isDisposed || firmware == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await _stopBootloaderScan();
|
await _stopBootloaderScan();
|
||||||
if (!mounted) {
|
if (!mounted || _isDisposed) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_clearBootloaderDevice();
|
_clearBootloaderDevice();
|
||||||
|
|||||||
Reference in New Issue
Block a user