Merge pull request #2992 from abarth/reactive_build
Reactivating a StatefulElement should imply a build
This commit is contained in:
commit
243a49f7d0
@ -626,11 +626,11 @@ class _InactiveElements {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void _deactivate(Element element) {
|
void _deactivateRecursively(Element element) {
|
||||||
assert(element._debugLifecycleState == _ElementLifecycle.active);
|
assert(element._debugLifecycleState == _ElementLifecycle.active);
|
||||||
element.deactivate();
|
element.deactivate();
|
||||||
assert(element._debugLifecycleState == _ElementLifecycle.inactive);
|
assert(element._debugLifecycleState == _ElementLifecycle.inactive);
|
||||||
element.visitChildren(_deactivate);
|
element.visitChildren(_deactivateRecursively);
|
||||||
assert(() { element.debugDeactivated(); return true; });
|
assert(() { element.debugDeactivated(); return true; });
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -639,7 +639,7 @@ class _InactiveElements {
|
|||||||
assert(!_elements.contains(element));
|
assert(!_elements.contains(element));
|
||||||
assert(element._parent == null);
|
assert(element._parent == null);
|
||||||
if (element._active)
|
if (element._active)
|
||||||
_deactivate(element);
|
_deactivateRecursively(element);
|
||||||
_elements.add(element);
|
_elements.add(element);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -840,12 +840,12 @@ abstract class Element implements BuildContext {
|
|||||||
_slot = newSlot;
|
_slot = newSlot;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _updateDepth() {
|
void _updateDepth(int parentDepth) {
|
||||||
int expectedDepth = _parent.depth + 1;
|
int expectedDepth = parentDepth + 1;
|
||||||
if (_depth < expectedDepth) {
|
if (_depth < expectedDepth) {
|
||||||
_depth = expectedDepth;
|
_depth = expectedDepth;
|
||||||
visitChildren((Element child) {
|
visitChildren((Element child) {
|
||||||
child._updateDepth();
|
child._updateDepth(expectedDepth);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -885,7 +885,7 @@ abstract class Element implements BuildContext {
|
|||||||
if (newChild != null) {
|
if (newChild != null) {
|
||||||
assert(newChild._parent == null);
|
assert(newChild._parent == null);
|
||||||
assert(() { _debugCheckForCycles(newChild); return true; });
|
assert(() { _debugCheckForCycles(newChild); return true; });
|
||||||
newChild.activate(this, newSlot);
|
newChild._activateWithParent(this, newSlot);
|
||||||
Element updatedChild = updateChild(newChild, newWidget, newSlot);
|
Element updatedChild = updateChild(newChild, newWidget, newSlot);
|
||||||
assert(newChild == updatedChild);
|
assert(newChild == updatedChild);
|
||||||
return updatedChild;
|
return updatedChild;
|
||||||
@ -917,16 +917,23 @@ abstract class Element implements BuildContext {
|
|||||||
_inactiveElements.add(child); // this eventually calls child.deactivate()
|
_inactiveElements.add(child); // this eventually calls child.deactivate()
|
||||||
}
|
}
|
||||||
|
|
||||||
void activate(Element parent, dynamic newSlot) {
|
void _activateWithParent(Element parent, dynamic newSlot) {
|
||||||
assert(_debugLifecycleState == _ElementLifecycle.inactive);
|
assert(_debugLifecycleState == _ElementLifecycle.inactive);
|
||||||
_parent = parent;
|
_parent = parent;
|
||||||
_reactivate();
|
_updateDepth(_parent.depth);
|
||||||
_updateDepth();
|
_activateRecursively(this);
|
||||||
attachRenderObject(newSlot);
|
attachRenderObject(newSlot);
|
||||||
assert(_debugLifecycleState == _ElementLifecycle.active);
|
assert(_debugLifecycleState == _ElementLifecycle.active);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _reactivate() {
|
static void _activateRecursively(Element element) {
|
||||||
|
assert(element._debugLifecycleState == _ElementLifecycle.inactive);
|
||||||
|
element.activate();
|
||||||
|
assert(element._debugLifecycleState == _ElementLifecycle.active);
|
||||||
|
element.visitChildren(_activateRecursively);
|
||||||
|
}
|
||||||
|
|
||||||
|
void activate() {
|
||||||
assert(_debugLifecycleState == _ElementLifecycle.inactive);
|
assert(_debugLifecycleState == _ElementLifecycle.inactive);
|
||||||
assert(widget != null);
|
assert(widget != null);
|
||||||
assert(depth != null);
|
assert(depth != null);
|
||||||
@ -934,7 +941,6 @@ abstract class Element implements BuildContext {
|
|||||||
_active = true;
|
_active = true;
|
||||||
_updateInheritance();
|
_updateInheritance();
|
||||||
assert(() { _debugLifecycleState = _ElementLifecycle.active; return true; });
|
assert(() { _debugLifecycleState = _ElementLifecycle.active; return true; });
|
||||||
visitChildren((Element child) => child._reactivate());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void deactivate() {
|
void deactivate() {
|
||||||
@ -1430,6 +1436,12 @@ class StatefulElement extends ComponentElement {
|
|||||||
rebuild();
|
rebuild();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void activate() {
|
||||||
|
super.activate();
|
||||||
|
markNeedsBuild();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void deactivate() {
|
void deactivate() {
|
||||||
_state.deactivate();
|
_state.deactivate();
|
||||||
|
@ -26,6 +26,29 @@ class StateMarkerState extends State<StateMarker> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class DeactivateLogger extends StatefulWidget {
|
||||||
|
DeactivateLogger({ Key key, this.log }) : super(key: key);
|
||||||
|
|
||||||
|
final List<String> log;
|
||||||
|
|
||||||
|
@override
|
||||||
|
DeactivateLoggerState createState() => new DeactivateLoggerState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class DeactivateLoggerState extends State<DeactivateLogger> {
|
||||||
|
@override
|
||||||
|
void deactivate() {
|
||||||
|
config.log.add('deactivate');
|
||||||
|
super.deactivate();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
config.log.add('build');
|
||||||
|
return new Container();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
test('can reparent state', () {
|
test('can reparent state', () {
|
||||||
testWidgets((WidgetTester tester) {
|
testWidgets((WidgetTester tester) {
|
||||||
@ -293,4 +316,28 @@ void main() {
|
|||||||
expect(keyState.marker, equals("marked"));
|
expect(keyState.marker, equals("marked"));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('Deactivate implies build', () {
|
||||||
|
testWidgets((WidgetTester tester) {
|
||||||
|
GlobalKey key = new GlobalKey();
|
||||||
|
List<String> log = <String>[];
|
||||||
|
DeactivateLogger logger = new DeactivateLogger(key: key, log: log);
|
||||||
|
|
||||||
|
tester.pumpWidget(
|
||||||
|
new Container(key: new UniqueKey(), child: logger)
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(log, equals(['build']));
|
||||||
|
|
||||||
|
tester.pumpWidget(
|
||||||
|
new Container(key: new UniqueKey(), child: logger)
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(log, equals(['build', 'deactivate', 'build']));
|
||||||
|
log.clear();
|
||||||
|
|
||||||
|
tester.pump();
|
||||||
|
expect(log, isEmpty);
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user