Merge pull request #1441 from abarth/delay_finalization
Delay unmounting elements until the end of the frame
This commit is contained in:
commit
4ebf26bfaa
@ -40,7 +40,7 @@ class WidgetFlutterBinding extends FlutterBinding {
|
|||||||
void beginFrame(double timeStamp) {
|
void beginFrame(double timeStamp) {
|
||||||
buildDirtyElements();
|
buildDirtyElements();
|
||||||
super.beginFrame(timeStamp);
|
super.beginFrame(timeStamp);
|
||||||
scheduleMicrotask(GlobalKey.checkForDuplicatesAndNotifyListeners);
|
Element.finalizeTree();
|
||||||
}
|
}
|
||||||
|
|
||||||
List<BuildableElement> _dirtyElements = new List<BuildableElement>();
|
List<BuildableElement> _dirtyElements = new List<BuildableElement>();
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
// 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:async';
|
||||||
import 'dart:collection';
|
import 'dart:collection';
|
||||||
|
|
||||||
import 'package:sky/rendering.dart';
|
import 'package:sky/rendering.dart';
|
||||||
@ -118,8 +119,7 @@ abstract class GlobalKey extends Key {
|
|||||||
assert(removed);
|
assert(removed);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void checkForDuplicatesAndNotifyListeners() {
|
static bool _debugCheckForDuplicates() {
|
||||||
assert(() {
|
|
||||||
String message = '';
|
String message = '';
|
||||||
for (GlobalKey key in _debugDuplicates.keys) {
|
for (GlobalKey key in _debugDuplicates.keys) {
|
||||||
message += 'Duplicate GlobalKey found amongst mounted elements: $key (${_debugDuplicates[key]} instances)\n';
|
message += 'Duplicate GlobalKey found amongst mounted elements: $key (${_debugDuplicates[key]} instances)\n';
|
||||||
@ -128,7 +128,9 @@ abstract class GlobalKey extends Key {
|
|||||||
if (!_debugDuplicates.isEmpty)
|
if (!_debugDuplicates.isEmpty)
|
||||||
throw message;
|
throw message;
|
||||||
return true;
|
return true;
|
||||||
});
|
}
|
||||||
|
|
||||||
|
static void _notifyListeners() {
|
||||||
if (_removedKeys.isEmpty)
|
if (_removedKeys.isEmpty)
|
||||||
return;
|
return;
|
||||||
try {
|
try {
|
||||||
@ -409,10 +411,55 @@ bool _canUpdate(Widget oldWidget, Widget newWidget) {
|
|||||||
|
|
||||||
enum _ElementLifecycle {
|
enum _ElementLifecycle {
|
||||||
initial,
|
initial,
|
||||||
mounted,
|
active,
|
||||||
|
inactive,
|
||||||
defunct,
|
defunct,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class _FreeElements {
|
||||||
|
bool _locked = false;
|
||||||
|
final Set<Element> _elements = new Set<Element>();
|
||||||
|
|
||||||
|
void _finalize(Element element) {
|
||||||
|
assert(element._debugLifecycleState == _ElementLifecycle.inactive);
|
||||||
|
element.unmount();
|
||||||
|
assert(element._debugLifecycleState == _ElementLifecycle.defunct);
|
||||||
|
element.visitChildren((Element child) {
|
||||||
|
assert(child._parent == element);
|
||||||
|
_finalize(child);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void finalizeAll() {
|
||||||
|
BuildableElement.lockState(() {
|
||||||
|
try {
|
||||||
|
_locked = true;
|
||||||
|
for (Element element in _elements)
|
||||||
|
_finalize(element);
|
||||||
|
} finally {
|
||||||
|
_elements.clear();
|
||||||
|
_locked = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void add(Element element) {
|
||||||
|
assert(!_locked);
|
||||||
|
assert(!_elements.contains(element));
|
||||||
|
assert(element._parent == null);
|
||||||
|
void deactivate(Element element) {
|
||||||
|
assert(element._debugLifecycleState == _ElementLifecycle.active);
|
||||||
|
element.deactivate();
|
||||||
|
assert(element._debugLifecycleState == _ElementLifecycle.inactive);
|
||||||
|
element.visitChildren(deactivate);
|
||||||
|
}
|
||||||
|
deactivate(element);
|
||||||
|
_elements.add(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final _FreeElements _freeElements = new _FreeElements();
|
||||||
|
|
||||||
typedef void ElementVisitor(Element element);
|
typedef void ElementVisitor(Element element);
|
||||||
|
|
||||||
abstract class BuildContext {
|
abstract class BuildContext {
|
||||||
@ -468,15 +515,6 @@ abstract class Element<T extends Widget> implements BuildContext {
|
|||||||
/// Calls the argument for each child. Must be overridden by subclasses that support having children.
|
/// Calls the argument for each child. Must be overridden by subclasses that support having children.
|
||||||
void visitChildren(ElementVisitor visitor) { }
|
void visitChildren(ElementVisitor visitor) { }
|
||||||
|
|
||||||
/// Calls the argument for each descendant, depth-first pre-order.
|
|
||||||
void visitDescendants(ElementVisitor visitor) {
|
|
||||||
void visit(Element element) {
|
|
||||||
visitor(element);
|
|
||||||
element.visitChildren(visit);
|
|
||||||
}
|
|
||||||
visitChildren(visit);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// This method is the core of the system.
|
/// This method is the core of the system.
|
||||||
///
|
///
|
||||||
/// It is called each time we are to add, update, or remove a child based on
|
/// It is called each time we are to add, update, or remove a child based on
|
||||||
@ -523,10 +561,16 @@ abstract class Element<T extends Widget> implements BuildContext {
|
|||||||
}
|
}
|
||||||
child = newWidget.createElement();
|
child = newWidget.createElement();
|
||||||
child.mount(this, newSlot);
|
child.mount(this, newSlot);
|
||||||
assert(child._debugLifecycleState == _ElementLifecycle.mounted);
|
assert(child._debugLifecycleState == _ElementLifecycle.active);
|
||||||
return child;
|
return child;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void finalizeTree() {
|
||||||
|
_freeElements.finalizeAll();
|
||||||
|
assert(GlobalKey._debugCheckForDuplicates);
|
||||||
|
scheduleMicrotask(GlobalKey._notifyListeners);
|
||||||
|
}
|
||||||
|
|
||||||
/// Called when an Element is given a new parent shortly after having been
|
/// Called when an Element is given a new parent shortly after having been
|
||||||
/// created. Use this to initialize state that depends on having a parent. For
|
/// created. Use this to initialize state that depends on having a parent. For
|
||||||
/// state that is independent of the position in the tree, it's better to just
|
/// state that is independent of the position in the tree, it's better to just
|
||||||
@ -535,7 +579,7 @@ abstract class Element<T extends Widget> implements BuildContext {
|
|||||||
assert(_debugLifecycleState == _ElementLifecycle.initial);
|
assert(_debugLifecycleState == _ElementLifecycle.initial);
|
||||||
assert(widget != null);
|
assert(widget != null);
|
||||||
assert(_parent == null);
|
assert(_parent == null);
|
||||||
assert(parent == null || parent._debugLifecycleState == _ElementLifecycle.mounted);
|
assert(parent == null || parent._debugLifecycleState == _ElementLifecycle.active);
|
||||||
assert(slot == null);
|
assert(slot == null);
|
||||||
assert(depth == null);
|
assert(depth == null);
|
||||||
_parent = parent;
|
_parent = parent;
|
||||||
@ -545,12 +589,12 @@ abstract class Element<T extends Widget> implements BuildContext {
|
|||||||
final GlobalKey key = widget.key;
|
final GlobalKey key = widget.key;
|
||||||
key._register(this);
|
key._register(this);
|
||||||
}
|
}
|
||||||
assert(() { _debugLifecycleState = _ElementLifecycle.mounted; return true; });
|
assert(() { _debugLifecycleState = _ElementLifecycle.active; return true; });
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Called when an Element receives a new configuration widget.
|
/// Called when an Element receives a new configuration widget.
|
||||||
void update(T newWidget) {
|
void update(T newWidget) {
|
||||||
assert(_debugLifecycleState == _ElementLifecycle.mounted);
|
assert(_debugLifecycleState == _ElementLifecycle.active);
|
||||||
assert(widget != null);
|
assert(widget != null);
|
||||||
assert(newWidget != null);
|
assert(newWidget != null);
|
||||||
assert(depth != null);
|
assert(depth != null);
|
||||||
@ -562,7 +606,7 @@ abstract class Element<T extends Widget> implements BuildContext {
|
|||||||
/// subclasses that have multiple children, to update the slot of a particular
|
/// subclasses that have multiple children, to update the slot of a particular
|
||||||
/// child when the child is moved in its child list.
|
/// child when the child is moved in its child list.
|
||||||
void updateSlotForChild(Element child, dynamic newSlot) {
|
void updateSlotForChild(Element child, dynamic newSlot) {
|
||||||
assert(_debugLifecycleState == _ElementLifecycle.mounted);
|
assert(_debugLifecycleState == _ElementLifecycle.active);
|
||||||
assert(child != null);
|
assert(child != null);
|
||||||
assert(child._parent == this);
|
assert(child._parent == this);
|
||||||
void visit(Element element) {
|
void visit(Element element) {
|
||||||
@ -574,40 +618,40 @@ abstract class Element<T extends Widget> implements BuildContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _updateSlot(dynamic newSlot) {
|
void _updateSlot(dynamic newSlot) {
|
||||||
assert(_debugLifecycleState == _ElementLifecycle.mounted);
|
assert(_debugLifecycleState == _ElementLifecycle.active);
|
||||||
assert(widget != null);
|
assert(widget != null);
|
||||||
assert(_parent != null);
|
assert(_parent != null);
|
||||||
assert(_parent._debugLifecycleState == _ElementLifecycle.mounted);
|
assert(_parent._debugLifecycleState == _ElementLifecycle.active);
|
||||||
assert(depth != null);
|
assert(depth != null);
|
||||||
_slot = newSlot;
|
_slot = newSlot;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void detachRenderObject() {
|
||||||
|
visitChildren((Element child) {
|
||||||
|
child.detachRenderObject();
|
||||||
|
});
|
||||||
|
_slot = null;
|
||||||
|
}
|
||||||
|
|
||||||
void _detachChild(Element child) {
|
void _detachChild(Element child) {
|
||||||
assert(child != null);
|
assert(child != null);
|
||||||
assert(child._parent == this);
|
assert(child._parent == this);
|
||||||
child._parent = null;
|
child._parent = null;
|
||||||
|
child.detachRenderObject();
|
||||||
bool haveDetachedRenderObject = false;
|
_freeElements.add(child);
|
||||||
void detach(Element descendant) {
|
|
||||||
if (!haveDetachedRenderObject) {
|
|
||||||
descendant._slot = null;
|
|
||||||
if (descendant is RenderObjectElement) {
|
|
||||||
descendant.detachRenderObject();
|
|
||||||
haveDetachedRenderObject = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
descendant.unmount();
|
|
||||||
assert(descendant._debugLifecycleState == _ElementLifecycle.defunct);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
detach(child);
|
void deactivate() {
|
||||||
child.visitDescendants(detach);
|
assert(_debugLifecycleState == _ElementLifecycle.active);
|
||||||
|
assert(widget != null);
|
||||||
|
assert(depth != null);
|
||||||
|
assert(() { _debugLifecycleState = _ElementLifecycle.inactive; return true; });
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Called when an Element is removed from the tree.
|
/// Called when an Element is removed from the tree.
|
||||||
/// Currently, an Element removed from the tree never returns.
|
/// Currently, an Element removed from the tree never returns.
|
||||||
void unmount() {
|
void unmount() {
|
||||||
assert(_debugLifecycleState == _ElementLifecycle.mounted);
|
assert(_debugLifecycleState == _ElementLifecycle.inactive);
|
||||||
assert(widget != null);
|
assert(widget != null);
|
||||||
assert(depth != null);
|
assert(depth != null);
|
||||||
if (widget.key is GlobalKey) {
|
if (widget.key is GlobalKey) {
|
||||||
@ -689,6 +733,8 @@ abstract class BuildableElement<T extends Widget> extends Element<T> {
|
|||||||
bool get dirty => _dirty;
|
bool get dirty => _dirty;
|
||||||
bool _dirty = true;
|
bool _dirty = true;
|
||||||
|
|
||||||
|
bool _active = false;
|
||||||
|
|
||||||
// We to let component authors call setState from initState, didUpdateConfig,
|
// We to let component authors call setState from initState, didUpdateConfig,
|
||||||
// and build even when state is locked because its convenient and a no-op
|
// and build even when state is locked because its convenient and a no-op
|
||||||
// anyway. This flag ensures that this convenience is only allowed on the
|
// anyway. This flag ensures that this convenience is only allowed on the
|
||||||
@ -703,6 +749,8 @@ abstract class BuildableElement<T extends Widget> extends Element<T> {
|
|||||||
void mount(Element parent, dynamic newSlot) {
|
void mount(Element parent, dynamic newSlot) {
|
||||||
super.mount(parent, newSlot);
|
super.mount(parent, newSlot);
|
||||||
assert(_child == null);
|
assert(_child == null);
|
||||||
|
assert(!_active);
|
||||||
|
_active = true;
|
||||||
rebuild();
|
rebuild();
|
||||||
assert(_child != null);
|
assert(_child != null);
|
||||||
}
|
}
|
||||||
@ -716,9 +764,11 @@ abstract class BuildableElement<T extends Widget> extends Element<T> {
|
|||||||
/// and by update() when the Widget has changed.
|
/// and by update() when the Widget has changed.
|
||||||
void rebuild() {
|
void rebuild() {
|
||||||
assert(_debugLifecycleState != _ElementLifecycle.initial);
|
assert(_debugLifecycleState != _ElementLifecycle.initial);
|
||||||
if (!dirty)
|
if (!_active || !_dirty) {
|
||||||
|
_dirty = false;
|
||||||
return;
|
return;
|
||||||
assert(_debugLifecycleState == _ElementLifecycle.mounted);
|
}
|
||||||
|
assert(_debugLifecycleState == _ElementLifecycle.active);
|
||||||
assert(_debugStateLocked);
|
assert(_debugStateLocked);
|
||||||
assert(_debugSetAllowIgnoredCallsToMarkNeedsBuild(true));
|
assert(_debugSetAllowIgnoredCallsToMarkNeedsBuild(true));
|
||||||
Widget built;
|
Widget built;
|
||||||
@ -778,10 +828,12 @@ abstract class BuildableElement<T extends Widget> extends Element<T> {
|
|||||||
/// the build itself.
|
/// the build itself.
|
||||||
void markNeedsBuild() {
|
void markNeedsBuild() {
|
||||||
assert(_debugLifecycleState != _ElementLifecycle.defunct);
|
assert(_debugLifecycleState != _ElementLifecycle.defunct);
|
||||||
|
if (!_active)
|
||||||
|
return;
|
||||||
|
assert(_debugLifecycleState == _ElementLifecycle.active);
|
||||||
assert(!_debugStateLocked || (_debugAllowIgnoredCallsToMarkNeedsBuild && dirty));
|
assert(!_debugStateLocked || (_debugAllowIgnoredCallsToMarkNeedsBuild && dirty));
|
||||||
if (dirty)
|
if (dirty)
|
||||||
return;
|
return;
|
||||||
assert(_debugLifecycleState == _ElementLifecycle.mounted);
|
|
||||||
assert(!_debugStateLocked);
|
assert(!_debugStateLocked);
|
||||||
_dirty = true;
|
_dirty = true;
|
||||||
assert(scheduleBuildFor != null);
|
assert(scheduleBuildFor != null);
|
||||||
@ -793,9 +845,10 @@ abstract class BuildableElement<T extends Widget> extends Element<T> {
|
|||||||
visitor(_child);
|
visitor(_child);
|
||||||
}
|
}
|
||||||
|
|
||||||
void unmount() {
|
void deactivate() {
|
||||||
super.unmount();
|
super.deactivate();
|
||||||
_dirty = false; // so that we don't get rebuilt even if we're already marked dirty
|
assert(_active == true);
|
||||||
|
_active = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void dependenciesChanged() {
|
void dependenciesChanged() {
|
||||||
@ -1051,7 +1104,7 @@ abstract class RenderObjectElement<T extends RenderObjectWidget> extends Element
|
|||||||
while ((childrenTop <= oldChildrenBottom) && (childrenTop <= newChildrenBottom)) {
|
while ((childrenTop <= oldChildrenBottom) && (childrenTop <= newChildrenBottom)) {
|
||||||
Element oldChild = oldChildren[childrenTop];
|
Element oldChild = oldChildren[childrenTop];
|
||||||
Widget newWidget = newWidgets[childrenTop];
|
Widget newWidget = newWidgets[childrenTop];
|
||||||
assert(oldChild._debugLifecycleState == _ElementLifecycle.mounted);
|
assert(oldChild._debugLifecycleState == _ElementLifecycle.active);
|
||||||
if (!_canUpdate(oldChild.widget, newWidget))
|
if (!_canUpdate(oldChild.widget, newWidget))
|
||||||
break;
|
break;
|
||||||
childrenTop += 1;
|
childrenTop += 1;
|
||||||
@ -1066,11 +1119,11 @@ abstract class RenderObjectElement<T extends RenderObjectWidget> extends Element
|
|||||||
while ((childrenTop <= oldChildrenBottom) && (childrenTop <= newChildrenBottom)) {
|
while ((childrenTop <= oldChildrenBottom) && (childrenTop <= newChildrenBottom)) {
|
||||||
Element oldChild = oldChildren[oldChildrenBottom];
|
Element oldChild = oldChildren[oldChildrenBottom];
|
||||||
Widget newWidget = newWidgets[newChildrenBottom];
|
Widget newWidget = newWidgets[newChildrenBottom];
|
||||||
assert(oldChild._debugLifecycleState == _ElementLifecycle.mounted);
|
assert(oldChild._debugLifecycleState == _ElementLifecycle.active);
|
||||||
if (!_canUpdate(oldChild.widget, newWidget))
|
if (!_canUpdate(oldChild.widget, newWidget))
|
||||||
break;
|
break;
|
||||||
Element newChild = updateChild(oldChild, newWidget, nextSibling);
|
Element newChild = updateChild(oldChild, newWidget, nextSibling);
|
||||||
assert(newChild._debugLifecycleState == _ElementLifecycle.mounted);
|
assert(newChild._debugLifecycleState == _ElementLifecycle.active);
|
||||||
newChildren[newChildrenBottom] = newChild;
|
newChildren[newChildrenBottom] = newChild;
|
||||||
nextSibling = newChild;
|
nextSibling = newChild;
|
||||||
oldChildrenBottom -= 1;
|
oldChildrenBottom -= 1;
|
||||||
@ -1084,7 +1137,7 @@ abstract class RenderObjectElement<T extends RenderObjectWidget> extends Element
|
|||||||
oldKeyedChildren = new Map<Key, Element>();
|
oldKeyedChildren = new Map<Key, Element>();
|
||||||
while (childrenTop <= oldChildrenBottom) {
|
while (childrenTop <= oldChildrenBottom) {
|
||||||
Element oldChild = oldChildren[oldChildrenBottom];
|
Element oldChild = oldChildren[oldChildrenBottom];
|
||||||
assert(oldChild._debugLifecycleState == _ElementLifecycle.mounted);
|
assert(oldChild._debugLifecycleState == _ElementLifecycle.active);
|
||||||
if (oldChild.widget.key != null)
|
if (oldChild.widget.key != null)
|
||||||
oldKeyedChildren[oldChild.widget.key] = oldChild;
|
oldKeyedChildren[oldChild.widget.key] = oldChild;
|
||||||
else
|
else
|
||||||
@ -1115,8 +1168,8 @@ abstract class RenderObjectElement<T extends RenderObjectWidget> extends Element
|
|||||||
}
|
}
|
||||||
assert(oldChild == null || _canUpdate(oldChild.widget, newWidget));
|
assert(oldChild == null || _canUpdate(oldChild.widget, newWidget));
|
||||||
Element newChild = updateChild(oldChild, newWidget, nextSibling);
|
Element newChild = updateChild(oldChild, newWidget, nextSibling);
|
||||||
assert(newChild._debugLifecycleState == _ElementLifecycle.mounted);
|
assert(newChild._debugLifecycleState == _ElementLifecycle.active);
|
||||||
assert(oldChild == newChild || oldChild == null || oldChild._debugLifecycleState != _ElementLifecycle.mounted);
|
assert(oldChild == newChild || oldChild == null || oldChild._debugLifecycleState != _ElementLifecycle.active);
|
||||||
newChildren[newChildrenBottom] = newChild;
|
newChildren[newChildrenBottom] = newChild;
|
||||||
nextSibling = newChild;
|
nextSibling = newChild;
|
||||||
newChildrenBottom -= 1;
|
newChildrenBottom -= 1;
|
||||||
@ -1128,12 +1181,12 @@ abstract class RenderObjectElement<T extends RenderObjectWidget> extends Element
|
|||||||
while (childrenTop > 0) {
|
while (childrenTop > 0) {
|
||||||
childrenTop -= 1;
|
childrenTop -= 1;
|
||||||
Element oldChild = oldChildren[childrenTop];
|
Element oldChild = oldChildren[childrenTop];
|
||||||
assert(oldChild._debugLifecycleState == _ElementLifecycle.mounted);
|
assert(oldChild._debugLifecycleState == _ElementLifecycle.active);
|
||||||
Widget newWidget = newWidgets[childrenTop];
|
Widget newWidget = newWidgets[childrenTop];
|
||||||
assert(_canUpdate(oldChild.widget, newWidget));
|
assert(_canUpdate(oldChild.widget, newWidget));
|
||||||
Element newChild = updateChild(oldChild, newWidget, nextSibling);
|
Element newChild = updateChild(oldChild, newWidget, nextSibling);
|
||||||
assert(newChild._debugLifecycleState == _ElementLifecycle.mounted);
|
assert(newChild._debugLifecycleState == _ElementLifecycle.active);
|
||||||
assert(oldChild == newChild || oldChild == null || oldChild._debugLifecycleState != _ElementLifecycle.mounted);
|
assert(oldChild == newChild || oldChild == null || oldChild._debugLifecycleState != _ElementLifecycle.active);
|
||||||
newChildren[childrenTop] = newChild;
|
newChildren[childrenTop] = newChild;
|
||||||
nextSibling = newChild;
|
nextSibling = newChild;
|
||||||
}
|
}
|
||||||
@ -1148,6 +1201,11 @@ abstract class RenderObjectElement<T extends RenderObjectWidget> extends Element
|
|||||||
return newChildren;
|
return newChildren;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void deactivate() {
|
||||||
|
super.deactivate();
|
||||||
|
assert(!renderObject.attached);
|
||||||
|
}
|
||||||
|
|
||||||
void unmount() {
|
void unmount() {
|
||||||
super.unmount();
|
super.unmount();
|
||||||
assert(!renderObject.attached);
|
assert(!renderObject.attached);
|
||||||
@ -1170,6 +1228,7 @@ abstract class RenderObjectElement<T extends RenderObjectWidget> extends Element
|
|||||||
_ancestorRenderObjectElement.removeChildRenderObject(renderObject);
|
_ancestorRenderObjectElement.removeChildRenderObject(renderObject);
|
||||||
_ancestorRenderObjectElement = null;
|
_ancestorRenderObjectElement = null;
|
||||||
}
|
}
|
||||||
|
_slot = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
void insertChildRenderObject(RenderObject child, dynamic slot);
|
void insertChildRenderObject(RenderObject child, dynamic slot);
|
||||||
@ -1301,7 +1360,7 @@ class MultiChildRenderObjectElement<T extends MultiChildRenderObjectWidget> exte
|
|||||||
for (int i = _children.length - 1; i >= 0; --i) {
|
for (int i = _children.length - 1; i >= 0; --i) {
|
||||||
Element newChild = widget.children[i].createElement();
|
Element newChild = widget.children[i].createElement();
|
||||||
newChild.mount(this, previousChild);
|
newChild.mount(this, previousChild);
|
||||||
assert(newChild._debugLifecycleState == _ElementLifecycle.mounted);
|
assert(newChild._debugLifecycleState == _ElementLifecycle.active);
|
||||||
_children[i] = newChild;
|
_children[i] = newChild;
|
||||||
previousChild = newChild;
|
previousChild = newChild;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user