Unverified Commit 9f4e5ad9 authored by chunhtai's avatar chunhtai Committed by GitHub

Fix ios black screen during splash screen if widget binding initializ… (#52913)

parent 602ac0bc
...@@ -774,7 +774,7 @@ mixin SchedulerBinding on BindingBase, ServicesBinding { ...@@ -774,7 +774,7 @@ mixin SchedulerBinding on BindingBase, ServicesBinding {
/// * [scheduleWarmUpFrame], which ignores the "Vsync" signal entirely and /// * [scheduleWarmUpFrame], which ignores the "Vsync" signal entirely and
/// triggers a frame immediately. /// triggers a frame immediately.
void scheduleFrame() { void scheduleFrame() {
if (_hasScheduledFrame || !_framesEnabled) if (_hasScheduledFrame || !framesEnabled)
return; return;
assert(() { assert(() {
if (debugPrintScheduleFrameStacks) if (debugPrintScheduleFrameStacks)
...@@ -808,7 +808,7 @@ mixin SchedulerBinding on BindingBase, ServicesBinding { ...@@ -808,7 +808,7 @@ mixin SchedulerBinding on BindingBase, ServicesBinding {
void scheduleForcedFrame() { void scheduleForcedFrame() {
// TODO(chunhtai): Removes the if case once the issue is fixed // TODO(chunhtai): Removes the if case once the issue is fixed
// https://github.com/flutter/flutter/issues/45131 // https://github.com/flutter/flutter/issues/45131
if (!_framesEnabled) if (!framesEnabled)
return; return;
if (_hasScheduledFrame) if (_hasScheduledFrame)
......
...@@ -907,6 +907,11 @@ mixin WidgetsBinding on BindingBase, ServicesBinding, SchedulerBinding, GestureB ...@@ -907,6 +907,11 @@ mixin WidgetsBinding on BindingBase, ServicesBinding, SchedulerBinding, GestureB
Element get renderViewElement => _renderViewElement; Element get renderViewElement => _renderViewElement;
Element _renderViewElement; Element _renderViewElement;
bool _readyToProduceFrames = false;
@override
bool get framesEnabled => super.framesEnabled && _readyToProduceFrames;
/// Schedules a [Timer] for attaching the root widget. /// Schedules a [Timer] for attaching the root widget.
/// ///
/// This is called by [runApp] to configure the widget tree. Consider using /// This is called by [runApp] to configure the widget tree. Consider using
...@@ -928,6 +933,7 @@ mixin WidgetsBinding on BindingBase, ServicesBinding, SchedulerBinding, GestureB ...@@ -928,6 +933,7 @@ mixin WidgetsBinding on BindingBase, ServicesBinding, SchedulerBinding, GestureB
/// * [RenderObjectToWidgetAdapter.attachToRenderTree], which inflates a /// * [RenderObjectToWidgetAdapter.attachToRenderTree], which inflates a
/// widget and attaches it to the render tree. /// widget and attaches it to the render tree.
void attachRootWidget(Widget rootWidget) { void attachRootWidget(Widget rootWidget) {
_readyToProduceFrames = true;
_renderViewElement = RenderObjectToWidgetAdapter<RenderBox>( _renderViewElement = RenderObjectToWidgetAdapter<RenderBox>(
container: renderView, container: renderView,
debugShortDescription: '[root]', debugShortDescription: '[root]',
......
// Copyright 2014 The Flutter 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 'dart:typed_data';
import 'package:flutter/scheduler.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/widgets.dart';
void main() {
test('Can only schedule frames after widget binding attaches the root widget', () async {
final WidgetsBinding binding = WidgetsFlutterBinding.ensureInitialized();
expect(SchedulerBinding.instance.framesEnabled, isFalse);
expect(SchedulerBinding.instance.hasScheduledFrame, isFalse);
// Sends a message to notify that the engine is ready to accept frames.
final ByteData message = const StringCodec().encodeMessage('AppLifecycleState.resumed');
await ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage('flutter/lifecycle', message, (_) { });
// Enables the semantics should not schedule any frames if the root widget
// has not been attached.
binding.setSemanticsEnabled(true);
expect(SchedulerBinding.instance.framesEnabled, isFalse);
expect(SchedulerBinding.instance.hasScheduledFrame, isFalse);
// The widget binding should be ready to produce frames after it attaches
// the root widget.
binding.attachRootWidget(const Placeholder());
expect(SchedulerBinding.instance.framesEnabled, isTrue);
expect(SchedulerBinding.instance.hasScheduledFrame, isTrue);
});
}
...@@ -28,6 +28,9 @@ void main() { ...@@ -28,6 +28,9 @@ void main() {
final ByteData message = const StringCodec().encodeMessage('AppLifecycleState.resumed'); final ByteData message = const StringCodec().encodeMessage('AppLifecycleState.resumed');
await ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage('flutter/lifecycle', message, (_) { }); await ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage('flutter/lifecycle', message, (_) { });
// A frame can only be scheduled when there is a root widget.
binding.attachRootWidget(const Placeholder());
// Frame callbacks are registered lazily when a frame is scheduled. // Frame callbacks are registered lazily when a frame is scheduled.
binding.scheduleFrame(); binding.scheduleFrame();
expect(window.onBeginFrame, isNotNull); expect(window.onBeginFrame, isNotNull);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment