diff --git a/bin/internal/engine.version b/bin/internal/engine.version index d3e1fb5184a..65b5d1b86bb 100644 --- a/bin/internal/engine.version +++ b/bin/internal/engine.version @@ -1 +1 @@ -f4951df193a7966f9ed4da43d555eee0913d84d1 +a48cd16e077778a7aa5908e4faa4da07714260f2 diff --git a/packages/flutter/lib/src/scheduler/binding.dart b/packages/flutter/lib/src/scheduler/binding.dart index d0b83853e47..f33ba8601dd 100644 --- a/packages/flutter/lib/src/scheduler/binding.dart +++ b/packages/flutter/lib/src/scheduler/binding.dart @@ -193,6 +193,7 @@ mixin SchedulerBinding on BindingBase, ServicesBinding { window.onBeginFrame = _handleBeginFrame; window.onDrawFrame = _handleDrawFrame; SystemChannels.lifecycle.setMessageHandler(_handleLifecycleMessage); + readInitialLifecycleStateFromNativeWindow(); } /// The current [SchedulerBinding], if one has been created. @@ -225,6 +226,23 @@ mixin SchedulerBinding on BindingBase, ServicesBinding { AppLifecycleState get lifecycleState => _lifecycleState; AppLifecycleState _lifecycleState; + /// Initializes the [lifecycleState] with the [initialLifecycleState] from the + /// window. + /// + /// Once the [lifecycleState] is populated through any means (including this + /// method), this method will do nothing. This is because the + /// [initialLifecycleState] may already be stale and it no longer makes sense + /// to use the initial state at dart vm startup as the current state anymore. + /// + /// The latest state should be obtained by subscribing to + /// [WidgetsBindingObserver.didChangeAppLifecycleState]. + @protected + void readInitialLifecycleStateFromNativeWindow() { + if (_lifecycleState == null && _parseAppLifecycleMessage(window.initialLifecycleState) != null) { + _handleLifecycleMessage(window.initialLifecycleState); + } + } + /// Called when the application lifecycle state changes. /// /// Notifies all the observers using diff --git a/packages/flutter/test/scheduler/lifecycle_test.dart b/packages/flutter/test/scheduler/lifecycle_test.dart new file mode 100644 index 00000000000..7506c1475ec --- /dev/null +++ b/packages/flutter/test/scheduler/lifecycle_test.dart @@ -0,0 +1,23 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:flutter_test/flutter_test.dart'; +import 'package:flutter/scheduler.dart'; + +void main() { + testWidgets('initialLifecycleState is used to init state paused', (WidgetTester tester) async { + // The lifecycleState is null initially in tests as there is no + // initialLifecycleState. + expect(SchedulerBinding.instance.lifecycleState, equals(null)); + // Mock the Window to provide paused as the AppLifecycleState + final TestWidgetsFlutterBinding binding = tester.binding; + // Use paused as the initial state. + binding.window.initialLifecycleStateTestValue = 'AppLifecycleState.paused'; + binding.readTestInitialLifecycleStateFromNativeWindow(); // Re-attempt the initializaiton. + + // The lifecycleState should now be the state we passed above, + // even though no lifecycle event was fired from the platform. + expect(SchedulerBinding.instance.lifecycleState.toString(), equals('AppLifecycleState.paused')); + }); +} diff --git a/packages/flutter_test/lib/src/binding.dart b/packages/flutter_test/lib/src/binding.dart index eae35756a10..1a4bd3819ce 100644 --- a/packages/flutter_test/lib/src/binding.dart +++ b/packages/flutter_test/lib/src/binding.dart @@ -257,6 +257,12 @@ abstract class TestWidgetsFlutterBinding extends BindingBase }); } + /// Re-attempts the initialization of the lifecycle state after providing + /// test values in [TestWindow.initialLifecycleStateTestValue]. + void readTestInitialLifecycleStateFromNativeWindow() { + readInitialLifecycleStateFromNativeWindow(); + } + Size _surfaceSize; /// Artificially changes the surface size to `size` on the Widget binding, diff --git a/packages/flutter_test/lib/src/window.dart b/packages/flutter_test/lib/src/window.dart index 8e5b5e93898..d4111f7d848 100644 --- a/packages/flutter_test/lib/src/window.dart +++ b/packages/flutter_test/lib/src/window.dart @@ -151,6 +151,14 @@ class TestWindow implements Window { _window.onLocaleChanged = callback; } + @override + String get initialLifecycleState => _initialLifecycleStateTestValue; + String _initialLifecycleStateTestValue; + /// Sets a faked initialLifecycleState for testing. + set initialLifecycleStateTestValue(String state) { + _initialLifecycleStateTestValue = state; + } + @override double get textScaleFactor => _textScaleFactorTestValue ?? _window.textScaleFactor; double _textScaleFactorTestValue;