Commit 67a18fa5 authored by Hans Muller's avatar Hans Muller

TwoLevelList fails to restore sublist expanded state

parent a8c108de
......@@ -154,11 +154,14 @@ class _TwoLevelSublistState extends State<TwoLevelSublist> {
}
class TwoLevelList extends StatelessWidget {
TwoLevelList({ Key key, this.items, this.type: MaterialListType.twoLine }) : super(key: key);
TwoLevelList({ Key key, this.scrollableKey, this.items, this.type: MaterialListType.twoLine }) : super(key: key);
final List<Widget> items;
final MaterialListType type;
final Key scrollableKey;
@override
Widget build(BuildContext context) => new Block(children: items);
Widget build(BuildContext context) {
return new Block(children: KeyedSubtree.ensureUniqueKeysForList(items), scrollableKey: scrollableKey);
}
}
......@@ -7,6 +7,7 @@ import 'dart:ui' as ui show Image;
import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';
import 'debug.dart';
import 'framework.dart';
export 'package:flutter/animation.dart';
......@@ -2575,6 +2576,27 @@ class KeyedSubtree extends StatelessWidget {
/// The widget below this widget in the tree.
final Widget child;
/// Wrap each item in a KeyedSubtree whose key is based on the item's existing key or
/// its list index + baseIndex.
static List<Widget> ensureUniqueKeysForList(Iterable<Widget> items, { int baseIndex: 0 }) {
if (items == null || items.isEmpty)
return items;
List<Widget> itemsWithUniqueKeys = <Widget>[];
int itemIndex = baseIndex;
for(Widget item in items) {
itemsWithUniqueKeys.add(new KeyedSubtree(
key: item.key != null ? new ValueKey<Key>(item.key) : new ValueKey<int>(itemIndex),
child: item
));
itemIndex += 1;
}
assert(!debugItemsHaveDuplicateKeys(itemsWithUniqueKeys));
return items;
}
@override
Widget build(BuildContext context) => child;
}
......
......@@ -25,22 +25,39 @@ bool debugCheckHasMediaQuery(BuildContext context) {
return true;
}
bool debugHasDuplicateKeys(Widget parent, Iterable<Widget> children) {
Key _firstNonUniqueKey(Iterable<Widget> widgets) {
Set<Key> keySet = new HashSet<Key>();
for (Widget widget in widgets) {
assert(widget != null);
if (widget.key == null)
continue;
if (!keySet.add(widget.key))
return widget.key;
}
return null;
}
bool debugChildrenHaveDuplicateKeys(Widget parent, Iterable<Widget> children) {
assert(() {
Set<Key> keySet = new HashSet<Key>();
for (Widget child in children) {
assert(child != null);
if (child.key == null)
continue;
if (!keySet.add(child.key)) {
throw new FlutterError(
'Duplicate keys found.\n'
'If multiple keyed nodes exist as children of another node, they must have unique keys.\n'
'$parent has multiple children with key "${child.key}".'
);
}
final Key nonUniqueKey = _firstNonUniqueKey(children);
if (nonUniqueKey != null) {
throw new FlutterError(
'Duplicate keys found.\n'
'If multiple keyed nodes exist as children of another node, they must have unique keys.\n'
'$parent has multiple children with key $nonUniqueKey.'
);
}
return true;
});
return false;
}
bool debugItemsHaveDuplicateKeys(Iterable<Widget> items) {
assert(() {
final Key nonUniqueKey = _firstNonUniqueKey(items);
if (nonUniqueKey != null)
throw new FlutterError('Duplicate key found: $nonUniqueKey.\n');
return true;
});
return false;
}
......@@ -1937,7 +1937,7 @@ class SingleChildRenderObjectElement extends RenderObjectElement {
/// Instantiation of RenderObjectWidgets that can have a list of children
class MultiChildRenderObjectElement extends RenderObjectElement {
MultiChildRenderObjectElement(MultiChildRenderObjectWidget widget) : super(widget) {
assert(!debugHasDuplicateKeys(widget, widget.children));
assert(!debugChildrenHaveDuplicateKeys(widget, widget.children));
}
@override
......
......@@ -173,8 +173,9 @@ abstract class VirtualViewportElement extends RenderObjectElement {
Key key = child.key != null ? new ValueKey<Key>(child.key) : new ValueKey<int>(childIndex);
newWidgets[i] = new RepaintBoundary(key: key, child: child);
}
assert(!debugHasDuplicateKeys(widget, newWidgets));
_materializedChildren = updateChildren(_materializedChildren, newWidgets);
assert(!debugChildrenHaveDuplicateKeys(widget, newWidgets));
_materializedChildren = updateChildren(_materializedChildren, newWidgets.toList());
}
@override
......
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