Handle transitions to AppLifecycleState.detached in lifecycle state generation (#142523)

Generates the correct lifecycle state transitions in ServicesBinding when detaching.
This commit is contained in:
maRci002 2024-02-07 19:01:22 +01:00 committed by GitHub
parent 8431cae884
commit 8e2da8414c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 20 additions and 12 deletions

View file

@ -289,12 +289,6 @@ mixin ServicesBinding on BindingBase, SchedulerBinding {
if (previousState == state) {
return const <AppLifecycleState>[];
}
if (previousState == AppLifecycleState.paused && state == AppLifecycleState.detached) {
// Handle the wrap-around from paused to detached
return const <AppLifecycleState>[
AppLifecycleState.detached,
];
}
final List<AppLifecycleState> stateChanges = <AppLifecycleState>[];
if (previousState == null) {
// If there was no previous state, just jump directly to the new state.
@ -304,7 +298,12 @@ mixin ServicesBinding on BindingBase, SchedulerBinding {
final int stateIndex = AppLifecycleState.values.indexOf(state);
assert(previousStateIndex != -1, 'State $previousState missing in stateOrder array');
assert(stateIndex != -1, 'State $state missing in stateOrder array');
if (previousStateIndex > stateIndex) {
if (state == AppLifecycleState.detached) {
for (int i = previousStateIndex + 1; i < AppLifecycleState.values.length; ++i) {
stateChanges.add(AppLifecycleState.values[i]);
}
stateChanges.add(AppLifecycleState.detached);
} else if (previousStateIndex > stateIndex) {
for (int i = stateIndex; i < previousStateIndex; ++i) {
stateChanges.insert(0, AppLifecycleState.values[i]);
}

View file

@ -129,10 +129,11 @@ void main() {
await setAppLifeCycleState(AppLifecycleState.resumed);
expect(transitions, equals(<String>['restart', 'show', 'resume']));
// Generates intermediate states.
// Generates intermediate states from lower to higher lifecycle states.
transitions.clear();
await setAppLifeCycleState(AppLifecycleState.paused);
expect(transitions, equals(<String>['inactive', 'hide', 'pause']));
// Wraps around from pause to detach.
await setAppLifeCycleState(AppLifecycleState.detached);
expect(transitions, equals(<String>['inactive', 'hide', 'pause', 'detach']));
@ -140,14 +141,16 @@ void main() {
expect(transitions, equals(<String>['inactive', 'hide', 'pause', 'detach', 'resume']));
await setAppLifeCycleState(AppLifecycleState.paused);
expect(transitions, equals(<String>['inactive', 'hide', 'pause', 'detach', 'resume', 'inactive', 'hide', 'pause']));
// Generates intermediate states from higher to lower lifecycle states.
transitions.clear();
await setAppLifeCycleState(AppLifecycleState.resumed);
expect(transitions, equals(<String>['restart', 'show', 'resume']));
// Asserts on bad transitions
await expectLater(() => setAppLifeCycleState(AppLifecycleState.detached), throwsAssertionError);
await setAppLifeCycleState(AppLifecycleState.paused);
// Go to detached
transitions.clear();
await setAppLifeCycleState(AppLifecycleState.detached);
expect(transitions, equals(<String>['inactive', 'hide', 'pause', 'detach']));
});
testWidgets('Receives exit requests', (WidgetTester tester) async {

View file

@ -224,7 +224,13 @@ void main() {
]);
observer.accumulatedStates.clear();
await expectLater(() async => setAppLifeCycleState(AppLifecycleState.detached), throwsAssertionError);
await setAppLifeCycleState(AppLifecycleState.detached);
expect(observer.accumulatedStates, <AppLifecycleState>[
AppLifecycleState.inactive,
AppLifecycleState.hidden,
AppLifecycleState.paused,
AppLifecycleState.detached,
]);
WidgetsBinding.instance.removeObserver(observer);
});