Unverified Commit 1b441333 authored by Todd Volkert's avatar Todd Volkert Committed by GitHub

Move ensureVisualUpdate call to call sites in WidgetsBinding.attachRootWidget() (#75811)

This call is unnecessary and wasteful for callers that are building
parallel widget trees, since for those use cases, the caller is
generally going to build the tree synchronously immediately.
parent 235927d5
...@@ -926,12 +926,16 @@ mixin WidgetsBinding on BindingBase, ServicesBinding, SchedulerBinding, GestureB ...@@ -926,12 +926,16 @@ 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) {
final bool isBootstrapFrame = renderViewElement == null;
_readyToProduceFrames = true; _readyToProduceFrames = true;
_renderViewElement = RenderObjectToWidgetAdapter<RenderBox>( _renderViewElement = RenderObjectToWidgetAdapter<RenderBox>(
container: renderView, container: renderView,
debugShortDescription: '[root]', debugShortDescription: '[root]',
child: rootWidget, child: rootWidget,
).attachToRenderTree(buildOwner!, renderViewElement as RenderObjectToWidgetElement<RenderBox>?); ).attachToRenderTree(buildOwner!, renderViewElement as RenderObjectToWidgetElement<RenderBox>?);
if (isBootstrapFrame) {
SchedulerBinding.instance!.ensureVisualUpdate();
}
} }
/// Whether the [renderViewElement] has been initialized. /// Whether the [renderViewElement] has been initialized.
...@@ -1094,9 +1098,6 @@ class RenderObjectToWidgetAdapter<T extends RenderObject> extends RenderObjectWi ...@@ -1094,9 +1098,6 @@ class RenderObjectToWidgetAdapter<T extends RenderObject> extends RenderObjectWi
owner.buildScope(element!, () { owner.buildScope(element!, () {
element!.mount(null, null); element!.mount(null, null);
}); });
// This is most likely the first time the framework is ready to produce
// a frame. Ensure that we are asked for one.
SchedulerBinding.instance!.ensureVisualUpdate();
} else { } else {
element._newWidget = this; element._newWidget = this;
element.markNeedsBuild(); element.markNeedsBuild();
......
...@@ -2,12 +2,38 @@ ...@@ -2,12 +2,38 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:ui' as ui;
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
const Size _kTestViewSize = Size(800.0, 600.0); const Size _kTestViewSize = Size(800.0, 600.0);
class ScheduledFrameTrackingWindow extends TestWindow {
ScheduledFrameTrackingWindow() : super(window: ui.window);
int _scheduledFrameCount = 0;
int get scheduledFrameCount => _scheduledFrameCount;
void resetScheduledFrameCount() {
_scheduledFrameCount = 0;
}
@override
void scheduleFrame() {
_scheduledFrameCount++;
super.scheduleFrame();
}
}
class ScheduledFrameTrackingBindings extends AutomatedTestWidgetsFlutterBinding {
final ScheduledFrameTrackingWindow _window = ScheduledFrameTrackingWindow();
@override
ScheduledFrameTrackingWindow get window => _window;
}
class OffscreenRenderView extends RenderView { class OffscreenRenderView extends RenderView {
OffscreenRenderView() : super( OffscreenRenderView() : super(
configuration: const ViewConfiguration(size: _kTestViewSize), configuration: const ViewConfiguration(size: _kTestViewSize),
...@@ -139,6 +165,20 @@ class TestFocusableState extends State<TestFocusable> { ...@@ -139,6 +165,20 @@ class TestFocusableState extends State<TestFocusable> {
} }
void main() { void main() {
// Override the bindings for this test suite so that we can track the number
// of times a frame has been scheduled.
ScheduledFrameTrackingBindings();
testWidgets('RenderObjectToWidgetAdapter.attachToRenderTree does not schedule frame', (WidgetTester tester) async {
expect(WidgetsBinding.instance, isA<ScheduledFrameTrackingBindings>());
final ScheduledFrameTrackingWindow window = WidgetsBinding.instance!.window as ScheduledFrameTrackingWindow;
window.resetScheduledFrameCount();
expect(window.scheduledFrameCount, isZero);
final OffscreenWidgetTree tree = OffscreenWidgetTree();
tree.pumpWidget(const SizedBox.shrink());
expect(window.scheduledFrameCount, isZero);
});
testWidgets('no crosstalk between widget build owners', (WidgetTester tester) async { testWidgets('no crosstalk between widget build owners', (WidgetTester tester) async {
final Trigger trigger1 = Trigger(); final Trigger trigger1 = Trigger();
final Counter counter1 = Counter(); final Counter counter1 = Counter();
......
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