diff --git a/flutter/lib/mobile/pages/remote_page.dart b/flutter/lib/mobile/pages/remote_page.dart index 74a5af45c..fe664bf22 100644 --- a/flutter/lib/mobile/pages/remote_page.dart +++ b/flutter/lib/mobile/pages/remote_page.dart @@ -126,6 +126,14 @@ class _RemotePageState extends State with WidgetsBindingObserver { @override Future dispose() async { WidgetsBinding.instance.removeObserver(this); + // Close the session up-front. `gFFI.close()` below only calls `sessionClose` + // after several awaits (canvas save, image update, the `enable_soft_keyboard` + // platform call), so if the app is backgrounded while this page is disposing, + // dispose can be suspended before reaching it and the connection is never torn + // down. The reconnect then re-attaches to the leaked session and is stuck on + // "Connecting...". Dispatching it here makes teardown happen synchronously on + // pop; the `sessionClose` in `gFFI.close()` becomes a no-op once removed. + unawaited(bind.sessionClose(sessionId: sessionId)); // https://github.com/flutter/flutter/issues/64935 super.dispose(); gFFI.dialogManager.hideMobileActionsOverlay(store: false);