Commit 78c74116 authored by Ian Hickson's avatar Ian Hickson Committed by GitHub

LayoutBuilder + GlobalKey + setState assert (#6068)

This silences an assertion that fired when reparenting a widget with a
global key inside a LayoutBuilder callback when that callback also
happened to call setState (directly or indirectly) on that widget.

Normally such setStates are considered ok since we know we haven't
cleaned that subtree yet, but we were not correctly handling the case
where the list needed resorting in that situation.
parent fa52b456
......@@ -1495,6 +1495,8 @@ class BuildOwner {
/// widget tree.
void markNeedsToResortDirtyElements() {
assert(() {
if (debugPrintScheduleBuildForStacks)
debugPrintStack(label: 'markNeedsToResortDirtyElements() called; _dirtyElementsNeedsResorting was $_dirtyElementsNeedsResorting (now true); dirty list is: $_dirtyElements');
if (_dirtyElementsNeedsResorting == null) {
throw new FlutterError(
'markNeedsToResortDirtyElements() called inappropriately.\n'
......@@ -1633,6 +1635,7 @@ class BuildOwner {
_debugCurrentBuildTarget = context;
return true;
});
_dirtyElementsNeedsResorting = false;
try {
callback();
} finally {
......
// Copyright 2016 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' hide TypeMatcher;
import 'package:flutter/widgets.dart';
class Wrapper extends StatelessWidget {
Wrapper({
Key key,
this.child,
}) : super(key: key);
final Widget child;
@override
Widget build(BuildContext context) => child;
}
class StatefulWrapper extends StatefulWidget {
StatefulWrapper({
Key key,
this.child,
}) : super(key: key);
final Widget child;
@override
StatefulWrapperState createState() => new StatefulWrapperState();
}
class StatefulWrapperState extends State<StatefulWrapper> {
void trigger() {
setState(() { /* for test purposes */ });
}
@override
Widget build(BuildContext context) => config.child;
}
void main() {
testWidgets('Moving global key inside a LayoutBuilder', (WidgetTester tester) async {
GlobalKey<StatefulWrapperState> key = new GlobalKey<StatefulWrapperState>();
await tester.pumpWidget(
new LayoutBuilder(builder: (BuildContext context, BoxConstraints constraints) {
return new Wrapper(
child: new StatefulWrapper(key: key, child: new Container(height: 100.0)),
);
}),
);
await tester.pumpWidget(
new LayoutBuilder(builder: (BuildContext context, BoxConstraints constraints) {
key.currentState.trigger();
return new StatefulWrapper(key: key, child: new Container(height: 100.0));
}),
);
});
}
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