Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
e8483fb3
Commit
e8483fb3
authored
Mar 08, 2016
by
Adam Barth
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Support reparenting state from MultiChildRenderObjectElement
Fixes #2085
parent
96a0e7cb
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
100 additions
and
11 deletions
+100
-11
framework.dart
packages/flutter/lib/src/widgets/framework.dart
+38
-11
reparent_state_test.dart
packages/flutter/test/widget/reparent_state_test.dart
+62
-0
No files found.
packages/flutter/lib/src/widgets/framework.dart
View file @
e8483fb3
...
...
@@ -1605,8 +1605,8 @@ abstract class RenderObjectElement<T extends RenderObjectWidget> extends Buildab
while
((
oldChildrenTop
<=
oldChildrenBottom
)
&&
(
newChildrenTop
<=
newChildrenBottom
))
{
Element
oldChild
=
oldChildren
[
oldChildrenTop
];
Widget
newWidget
=
newWidgets
[
newChildrenTop
];
assert
(
oldChild
.
_debugLifecycleState
==
_ElementLifecycle
.
active
);
if
(!
Widget
.
canUpdate
(
oldChild
.
widget
,
newWidget
))
assert
(
oldChild
==
null
||
oldChild
.
_debugLifecycleState
==
_ElementLifecycle
.
active
);
if
(
oldChild
==
null
||
!
Widget
.
canUpdate
(
oldChild
.
widget
,
newWidget
))
break
;
Element
newChild
=
updateChild
(
oldChild
,
newWidget
,
previousChild
);
assert
(
newChild
.
_debugLifecycleState
==
_ElementLifecycle
.
active
);
...
...
@@ -1620,8 +1620,8 @@ abstract class RenderObjectElement<T extends RenderObjectWidget> extends Buildab
while
((
oldChildrenTop
<=
oldChildrenBottom
)
&&
(
newChildrenTop
<=
newChildrenBottom
))
{
Element
oldChild
=
oldChildren
[
oldChildrenBottom
];
Widget
newWidget
=
newWidgets
[
newChildrenBottom
];
assert
(
oldChild
.
_debugLifecycleState
==
_ElementLifecycle
.
active
);
if
(!
Widget
.
canUpdate
(
oldChild
.
widget
,
newWidget
))
assert
(
oldChild
==
null
||
oldChild
.
_debugLifecycleState
==
_ElementLifecycle
.
active
);
if
(
oldChild
==
null
||
!
Widget
.
canUpdate
(
oldChild
.
widget
,
newWidget
))
break
;
oldChildrenBottom
-=
1
;
newChildrenBottom
-=
1
;
...
...
@@ -1634,11 +1634,13 @@ abstract class RenderObjectElement<T extends RenderObjectWidget> extends Buildab
oldKeyedChildren
=
new
Map
<
Key
,
Element
>();
while
(
oldChildrenTop
<=
oldChildrenBottom
)
{
Element
oldChild
=
oldChildren
[
oldChildrenTop
];
assert
(
oldChild
.
_debugLifecycleState
==
_ElementLifecycle
.
active
);
if
(
oldChild
.
widget
.
key
!=
null
)
oldKeyedChildren
[
oldChild
.
widget
.
key
]
=
oldChild
;
else
_deactivateChild
(
oldChild
);
assert
(
oldChild
==
null
||
oldChild
.
_debugLifecycleState
==
_ElementLifecycle
.
active
);
if
(
oldChild
!=
null
)
{
if
(
oldChild
.
widget
.
key
!=
null
)
oldKeyedChildren
[
oldChild
.
widget
.
key
]
=
oldChild
;
else
_deactivateChild
(
oldChild
);
}
oldChildrenTop
+=
1
;
}
}
...
...
@@ -1682,6 +1684,7 @@ abstract class RenderObjectElement<T extends RenderObjectWidget> extends Buildab
// Update the bottom of the list.
while
((
oldChildrenTop
<=
oldChildrenBottom
)
&&
(
newChildrenTop
<=
newChildrenBottom
))
{
Element
oldChild
=
oldChildren
[
oldChildrenTop
];
assert
(
oldChild
!=
null
);
assert
(
oldChild
.
_debugLifecycleState
==
_ElementLifecycle
.
active
);
Widget
newWidget
=
newWidgets
[
newChildrenTop
];
assert
(
Widget
.
canUpdate
(
oldChild
.
widget
,
newWidget
));
...
...
@@ -1826,6 +1829,19 @@ class MultiChildRenderObjectElement<T extends MultiChildRenderObjectWidget> exte
}
List
<
Element
>
_children
;
// We null out detached children lazily to avoid O(n^2) work walking _children
// repeatedly to remove children.
Set
<
Element
>
_detachedChildren
;
void
_replaceDetachedChildrenWithNull
()
{
if
(
_detachedChildren
!=
null
&&
_detachedChildren
.
isNotEmpty
)
{
for
(
int
i
=
0
;
i
<
_children
.
length
;
++
i
)
{
if
(
_detachedChildren
.
contains
(
_children
[
i
]))
_children
[
i
]
=
null
;
}
_detachedChildren
.
clear
();
}
}
void
insertChildRenderObject
(
RenderObject
child
,
Element
slot
)
{
final
ContainerRenderObjectMixin
renderObject
=
this
.
renderObject
;
...
...
@@ -1865,8 +1881,18 @@ class MultiChildRenderObjectElement<T extends MultiChildRenderObjectWidget> exte
}
void
visitChildren
(
ElementVisitor
visitor
)
{
for
(
Element
child
in
_children
)
visitor
(
child
);
_replaceDetachedChildrenWithNull
();
for
(
Element
child
in
_children
)
{
if
(
child
!=
null
)
visitor
(
child
);
}
}
bool
detachChild
(
Element
child
)
{
_detachedChildren
??=
new
Set
<
Element
>();
_detachedChildren
.
add
(
child
);
_deactivateChild
(
child
);
return
true
;
}
void
mount
(
Element
parent
,
dynamic
newSlot
)
{
...
...
@@ -1883,6 +1909,7 @@ class MultiChildRenderObjectElement<T extends MultiChildRenderObjectWidget> exte
void
update
(
T
newWidget
)
{
super
.
update
(
newWidget
);
assert
(
widget
==
newWidget
);
_replaceDetachedChildrenWithNull
();
_children
=
updateChildren
(
_children
,
widget
.
children
);
}
}
...
...
packages/flutter/test/widget/reparent_state_test.dart
View file @
e8483fb3
...
...
@@ -95,6 +95,68 @@ void main() {
});
});
test
(
'can reparent state with multichild widgets'
,
()
{
testWidgets
((
WidgetTester
tester
)
{
GlobalKey
left
=
new
GlobalKey
();
GlobalKey
right
=
new
GlobalKey
();
StateMarker
grandchild
=
new
StateMarker
();
tester
.
pumpWidget
(
new
Stack
(
children:
<
Widget
>[
new
StateMarker
(
key:
left
),
new
StateMarker
(
key:
right
,
child:
grandchild
)
]
)
);
(
left
.
currentState
as
StateMarkerState
).
marker
=
"left"
;
(
right
.
currentState
as
StateMarkerState
).
marker
=
"right"
;
StateMarkerState
grandchildState
=
tester
.
findStateByConfig
(
grandchild
);
expect
(
grandchildState
,
isNotNull
);
grandchildState
.
marker
=
"grandchild"
;
StateMarker
newGrandchild
=
new
StateMarker
();
tester
.
pumpWidget
(
new
Stack
(
children:
<
Widget
>[
new
StateMarker
(
key:
right
,
child:
newGrandchild
),
new
StateMarker
(
key:
left
)
]
)
);
expect
((
left
.
currentState
as
StateMarkerState
).
marker
,
equals
(
"left"
));
expect
((
right
.
currentState
as
StateMarkerState
).
marker
,
equals
(
"right"
));
StateMarkerState
newGrandchildState
=
tester
.
findStateByConfig
(
newGrandchild
);
expect
(
newGrandchildState
,
isNotNull
);
expect
(
newGrandchildState
,
equals
(
grandchildState
));
expect
(
newGrandchildState
.
marker
,
equals
(
"grandchild"
));
tester
.
pumpWidget
(
new
Center
(
child:
new
Container
(
child:
new
StateMarker
(
key:
left
,
child:
new
Container
()
)
)
)
);
expect
((
left
.
currentState
as
StateMarkerState
).
marker
,
equals
(
"left"
));
expect
(
right
.
currentState
,
isNull
);
});
});
test
(
'can with scrollable list'
,
()
{
testWidgets
((
WidgetTester
tester
)
{
GlobalKey
key
=
new
GlobalKey
();
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment