问题
Is there a way to explicitly tell a firebase animated list what the height of a specific widget should be? In my case, each item in the firebase list has a variable size based on a number of children (it's a comment thread). Whenever a large thread is out (above) of the viewport it is disposed of and the height is forgotten, this leads to annoying blocking and failure when trying to scroll back up.
Here is my thread:
new FirebaseAnimatedList(
defaultChild: new DefaultThreadView(),
query: ref.child(postKey),
sort: (a, b) => (a.key.compareTo(b.key)),
itemBuilder: (context, DataSnapshot snapshot,
Animation<double> animation) {
return new FutureBuilder<DataSnapshot>(
future: ref.child(postKey).child(snapshot.key).once(),
builder: (BuildContext context,
AsyncSnapshot<DataSnapshot> snap) {
switch (snap.connectionState) {
case ConnectionState.none:
return new Center(
child: new CircularProgressIndicator());
case ConnectionState.waiting:
return new Center(
child: new CircularProgressIndicator());
default:
if (!snap.hasData) {
return new Text('Error: ${snap.error}');
}
else {
//check if this snap is a root node
String parent = snap.data.value['parent'];
if (parent == this.postKey) {
return new replyTile.ReplyTile(
snap.data, animation, this.postKey, 0);
} else {
return new Container();
}
}
}
}
);
}
)
the reply tile is a widget to display the data and checks if it has any children and if it does it recurses.
Whenever a top parent reply tile goes out of the viewport it is disposed as expected but when trying to bring it back into view it scrolls right to the top and looks very jumpy, even worse whenever a bigger thread(with multiple children) tries to come back into view it doesn't scroll at all.
I think if the list view was aware of the height the scroll problem would go away but I could be wrong
Worse case how do I make it so the widget is not exposed and the whole thread is loaded from the start?
回答1:
You're doing asynchronous loading while the user is scrolling through the list and using the results of those asynchronous loads to set the height of your list items. This is leading to scrolling problems when rebuilding old items since their height isn't available at the moment they are built.
You could try loading whole thread into a Map and build your widgets with a regular ListView. That way all the data is there in memory for you to read when you need it. This would lead to a better user experience when scrolling to see new content (no progress indicators), but you wouldn't get updates when data changes and you might run out of memory for exceptionally long threads. Keep in mind that FirebaseAnimatedList maintains the full list of results from the initial query in memory anyway, like Firebase Database UI on other platforms.
If you don't like that option, you could cache the completed snapshots in a Map that you can read from so a loading indicator is never displayed when scrolling back to an old tile. You could still run out of memory if you don't implement some kind of eviction logic but it's less likely to happen in practice.
There isn't a way to paginate FirebaseAnimatedList yet, but I've been thinking about adding that.
来源:https://stackoverflow.com/questions/44479214/in-a-firebase-animated-list-is-there-a-way-to-let-firebase-list-know-the-expect