Commit bcd0d8fe authored by Adam Barth's avatar Adam Barth

Remove the flicker from MimicOverlay

There were two problems:

1) When starting the mimic, we put up a bad frame because although we set the
   `begin` value of the animation, we were building using the current `value`,
   which hadn't been updated.

2) When stoping the mimic, we'd dirty a component during didUnmount, which
   wouldn't get cleaned until the next frame. Now we're sure to clean all the
   components before leaving flushBuild.
parent 66e64023
...@@ -116,7 +116,7 @@ abstract class GlobalKey extends Key { ...@@ -116,7 +116,7 @@ abstract class GlobalKey extends Key {
} }
static void _notifyListeners() { static void _notifyListeners() {
assert(!_inRenderDirtyComponents); assert(!_inBuildDirtyComponents);
assert(!Widget._notifyingMountStatus); assert(!Widget._notifyingMountStatus);
assert(_debugDuplicates.isEmpty); assert(_debugDuplicates.isEmpty);
_notifyingListeners = true; _notifyingListeners = true;
...@@ -161,7 +161,7 @@ abstract class Widget { ...@@ -161,7 +161,7 @@ abstract class Widget {
} }
// you should not build the UI tree ahead of time, build it only during build() // you should not build the UI tree ahead of time, build it only during build()
bool _isConstructedDuringBuild() => this is AbstractWidgetRoot || this is App || _inRenderDirtyComponents || _inLayoutCallbackBuilder > 0; bool _isConstructedDuringBuild() => this is AbstractWidgetRoot || this is App || _inBuildDirtyComponents || _inLayoutCallbackBuilder > 0;
Key _key; Key _key;
...@@ -755,7 +755,7 @@ abstract class StatefulComponent extends Component { ...@@ -755,7 +755,7 @@ abstract class StatefulComponent extends Component {
Set<Component> _dirtyComponents = new Set<Component>(); Set<Component> _dirtyComponents = new Set<Component>();
bool _buildScheduled = false; bool _buildScheduled = false;
bool _inRenderDirtyComponents = false; bool _inBuildDirtyComponents = false;
int _inLayoutCallbackBuilder = 0; int _inLayoutCallbackBuilder = 0;
class LayoutCallbackBuilderHandle { bool _active = true; } class LayoutCallbackBuilderHandle { bool _active = true; }
...@@ -793,31 +793,33 @@ void _buildDirtyComponents() { ...@@ -793,31 +793,33 @@ void _buildDirtyComponents() {
if (_shouldLogRenderDuration) if (_shouldLogRenderDuration)
sw = new Stopwatch()..start(); sw = new Stopwatch()..start();
_inRenderDirtyComponents = true; while (!_dirtyComponents.isEmpty) {
try { _inBuildDirtyComponents = true;
sky.tracing.begin('Component.flushBuild'); try {
List<Component> sortedDirtyComponents = new List<Component>(); sky.tracing.begin('Component.flushBuild');
_absorbDirtyComponents(sortedDirtyComponents); List<Component> sortedDirtyComponents = new List<Component>();
int index = 0; _absorbDirtyComponents(sortedDirtyComponents);
while (index < sortedDirtyComponents.length) { int index = 0;
Component component = sortedDirtyComponents[index]; while (index < sortedDirtyComponents.length) {
component._buildIfDirty(); Component component = sortedDirtyComponents[index];
if (_dirtyComponents.length > 0) { component._buildIfDirty();
// the following assert verifies that we're not rebuilding anyone twice in one frame if (_dirtyComponents.length > 0) {
assert(_dirtyComponents.every((Component component) => !sortedDirtyComponents.contains(component))); // the following assert verifies that we're not rebuilding anyone twice in one frame
_absorbDirtyComponents(sortedDirtyComponents); assert(_dirtyComponents.every((Component component) => !sortedDirtyComponents.contains(component)));
index = 0; _absorbDirtyComponents(sortedDirtyComponents);
} else { index = 0;
index += 1; } else {
index += 1;
}
} }
} finally {
_buildScheduled = false;
_inBuildDirtyComponents = false;
sky.tracing.end('Component.flushBuild');
} }
} finally {
_buildScheduled = false;
_inRenderDirtyComponents = false;
sky.tracing.end('Component.flushBuild');
}
Widget._notifyMountStatusChanged(); Widget._notifyMountStatusChanged();
}
if (_shouldLogRenderDuration) { if (_shouldLogRenderDuration) {
sw.stop(); sw.stop();
......
...@@ -70,8 +70,9 @@ class MimicOverlay extends AnimatedComponent { ...@@ -70,8 +70,9 @@ class MimicOverlay extends AnimatedComponent {
setState(() { setState(() {
// TODO(abarth): We need to convert global bounds into local coordinates. // TODO(abarth): We need to convert global bounds into local coordinates.
_mimicBounds.begin = globalToLocal(globalBounds.topLeft) & globalBounds.size; _mimicBounds.begin = globalToLocal(globalBounds.topLeft) & globalBounds.size;
_expandPerformance.forward(); _mimicBounds.value = _mimicBounds.begin;
}); });
_expandPerformance.forward();
} }
Widget build() { Widget build() {
......
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