diff --git a/packages/flutter/lib/src/widgets/framework.dart b/packages/flutter/lib/src/widgets/framework.dart index 4e61e86456..990499c770 100644 --- a/packages/flutter/lib/src/widgets/framework.dart +++ b/packages/flutter/lib/src/widgets/framework.dart @@ -1165,6 +1165,13 @@ abstract class BuildableElement extends Element { assert(_debugLifecycleState == _ElementLifecycle.active); assert(() { if (_debugBuilding) { + if (_debugCurrentBuildTarget == null) { + // If _debugCurrentBuildTarget is null, we're not actually building a + // widget but instead building the root of the tree via runApp. + // TODO(abarth): Remove these cases and ensure that we always have + // a current build target when we're building. + return true; + } bool foundTarget = false; visitAncestorElements((Element element) { if (element == _debugCurrentBuildTarget) { @@ -1214,17 +1221,12 @@ abstract class BuildableElement extends Element { _debugCurrentBuildTarget = this; return true; }); - try { - performRebuild(); - } catch (e, stack) { - _debugReportException('rebuilding $this', e, stack); - } finally { - assert(() { - assert(_debugCurrentBuildTarget == this); - _debugCurrentBuildTarget = debugPreviousBuildTarget; - return true; - }); - } + performRebuild(); + assert(() { + assert(_debugCurrentBuildTarget == this); + _debugCurrentBuildTarget = debugPreviousBuildTarget; + return true; + }); assert(!_dirty); } @@ -1618,6 +1620,7 @@ abstract class RenderObjectElement extends BuildableElement { @override void performRebuild() { + widget.updateRenderObject(this, renderObject); _dirty = false; } diff --git a/packages/flutter/test/widget/render_object_widget_test.dart b/packages/flutter/test/widget/render_object_widget_test.dart index f7301b6b04..e1e72c5f86 100644 --- a/packages/flutter/test/widget/render_object_widget_test.dart +++ b/packages/flutter/test/widget/render_object_widget_test.dart @@ -20,6 +20,27 @@ class TestWidget extends StatelessWidget { Widget build(BuildContext context) => child; } +class TestOrientedBox extends SingleChildRenderObjectWidget { + TestOrientedBox({ Key key, Widget child }) : super(key: key, child: child); + + Decoration _getDecoration(BuildContext context) { + switch (MediaQuery.of(context).orientation) { + case Orientation.landscape: + return new BoxDecoration(backgroundColor: const Color(0xFF00FF00)); + case Orientation.portrait: + return new BoxDecoration(backgroundColor: const Color(0xFF0000FF)); + } + } + + @override + RenderDecoratedBox createRenderObject(BuildContext context) => new RenderDecoratedBox(decoration: _getDecoration(context)); + + @override + void updateRenderObject(BuildContext context, RenderDecoratedBox renderObject) { + renderObject.decoration = _getDecoration(context); + } +} + void main() { test('RenderObjectWidget smoke test', () { testWidgets((WidgetTester tester) { @@ -171,4 +192,28 @@ void main() { expect(grandChild.child, isNull); }); }); + + test('Can watch inherited widgets', () { + testWidgets((WidgetTester tester) { + Key boxKey = new UniqueKey(); + TestOrientedBox box = new TestOrientedBox(key: boxKey); + + tester.pumpWidget(new MediaQuery( + data: new MediaQueryData(size: const Size(400.0, 300.0)), + child: box + )); + + RenderDecoratedBox renderBox = tester.findElementByKey(boxKey).renderObject; + BoxDecoration decoration = renderBox.decoration; + expect(decoration.backgroundColor, equals(new Color(0xFF00FF00))); + + tester.pumpWidget(new MediaQuery( + data: new MediaQueryData(size: const Size(300.0, 400.0)), + child: box + )); + + decoration = renderBox.decoration; + expect(decoration.backgroundColor, equals(new Color(0xFF0000FF))); + }); + }); }