fix(app): make ConnectButton listener lifecycle-safe
Keep the exact VpnConnection instance used for listener registration so lifecycle cleanup does not depend on a deactivated BuildContext.
This commit is contained in:
1 parent
9ac236a981
commit
7ccca5340c
1 file changed
+14
-10
@@ -19,6 +19,7 @@ class _ConnectButtonState extends State<ConnectButton>
|
|||||||
DateTime _lastTap = DateTime.fromMillisecondsSinceEpoch(0);
|
DateTime _lastTap = DateTime.fromMillisecondsSinceEpoch(0);
|
||||||
AnimationController? _pulse;
|
AnimationController? _pulse;
|
||||||
Animation<double>? _pulseAnim;
|
Animation<double>? _pulseAnim;
|
||||||
|
VpnConnection? _vpn;
|
||||||
|
|
||||||
double get _pulseValue => _pulseAnim?.value ?? 0.0;
|
double get _pulseValue => _pulseAnim?.value ?? 0.0;
|
||||||
|
|
||||||
@@ -35,20 +36,25 @@ class _ConnectButtonState extends State<ConnectButton>
|
|||||||
);
|
);
|
||||||
WidgetsBinding.instance.addObserver(this);
|
WidgetsBinding.instance.addObserver(this);
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
if (mounted) context.read<VpnConnection>().addListener(_onVpnChanged);
|
if (!mounted || _vpn != null) return;
|
||||||
|
final vpn = context.read<VpnConnection>();
|
||||||
|
_vpn = vpn;
|
||||||
|
vpn.addListener(_onVpnChanged);
|
||||||
|
_onVpnChanged();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
WidgetsBinding.instance.removeObserver(this);
|
WidgetsBinding.instance.removeObserver(this);
|
||||||
context.read<VpnConnection>().removeListener(_onVpnChanged);
|
_vpn?.removeListener(_onVpnChanged);
|
||||||
_pulse?.dispose();
|
_pulse?.dispose();
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
void _onVpnChanged() {
|
void _onVpnChanged() {
|
||||||
final vpn = context.read<VpnConnection>();
|
final vpn = _vpn;
|
||||||
|
if (vpn == null) return;
|
||||||
if (vpn.status == VpnStatus.connected) {
|
if (vpn.status == VpnStatus.connected) {
|
||||||
_pulse?.repeat(reverse: true);
|
_pulse?.repeat(reverse: true);
|
||||||
} else {
|
} else {
|
||||||
@@ -60,14 +66,12 @@ class _ConnectButtonState extends State<ConnectButton>
|
|||||||
@override
|
@override
|
||||||
void didChangeAppLifecycleState(AppLifecycleState state) {
|
void didChangeAppLifecycleState(AppLifecycleState state) {
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
if (state == AppLifecycleState.paused ||
|
if (state != AppLifecycleState.resumed) {
|
||||||
state == AppLifecycleState.detached) {
|
|
||||||
_pulse?.stop();
|
_pulse?.stop();
|
||||||
} else if (state == AppLifecycleState.resumed) {
|
return;
|
||||||
final vpn = context.read<VpnConnection>();
|
}
|
||||||
if (vpn.status == VpnStatus.connected) {
|
if (_vpn?.status == VpnStatus.connected) {
|
||||||
_pulse?.repeat(reverse: true);
|
_pulse?.repeat(reverse: true);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user