我正在关注官方文档中的示例:https://flutter.io/catalog/samples/expansion-tile-sample/
我添加了一个StreamSubscription,每当Firebase数据库有一个新条目时返回。每次返回时,我都会更新示例中的data
并致电setState(){data = newData}
。
理论上这应该用新值重建整个ListView并且它工作得很好但是,最大的问题是当重建发生时,所有ExpansionTiles都会崩溃到默认状态,如果频繁更新,界面将完全无法使用。 / p>
有没有人知道如何使用官方文档中的示例,但每次都没有使用ExpansionTiles?
答案 0 :(得分:0)
ExpansionTile
状态丢失的原因是重新生成数据后它不再具有相同的密钥。以下是我在documentation code you linked in your question之上运行的实验。我只关注关键部分,即为ExpansionTile
分配密钥的位置:
Widget _buildTiles(Entry root) {
if (root.children.isEmpty) return new ListTile(title: new Text(root.title));
return new ExpansionTile(
key: new PageStorageKey<Entry>(root),
title: new Text(root.title),
children: root.children.map(_buildTiles).toList(),
);
}
由于您最有可能使用不可变数据,因此当您从Firebase获取新数据时,您会从中生成新对象。尽管root
具有相同的数据且与您相同,但它与Flutter的对象不同。你现在有两种处理方法。一个是覆盖==
,我认为这是一个坏主意,并将通过评论解释原因。第二种方法是从您知道相同的数据属性生成密钥(如唯一的数据库密钥)。我为我的例子选择了title
属性。
Widget _buildTiles(Entry root) {
if (root.children.isEmpty) return new ListTile(title: new Text(root.title));
return new ExpansionTile(
key: new PageStorageKey<String>(root.title), // root.title == newerRoot.title is true
title: new Text(root.title),
children: root.children.map(_buildTiles).toList(),
);
}
您可以使用this gist中的更新代码自行尝试。我还必须对文档中的原始代码进行一些修改,以便我可以刷新数据并模拟您的情况。