I have a listView in my screen. I have attached a controller to it. I am able to call my Endpoint, receive response, parse it and insert in row. ListView supposed to Scroll automatically. It does, but not in perfect way. I am always an item behind. This is my code:
@override
Widget build(BuildContext context) {
// Scroll to the most recent item
if (equationList.length > 0) {
_toEnd();
}
return new Scaffold(
appBar: new AppBar(
title: new Text(widget.title),
),
body: EquList(equationList, _scrollController),
floatingActionButton: new FloatingActionButton(
onPressed: onFabClick,
tooltip: 'Fetch Post',
child: new Icon(isLoading ? Icons.pause : Icons.play_arrow),
),
);
}
void _toEnd() {
_scrollController.animateTo(
_scrollController.position.maxScrollExtent,
duration: const Duration(milliseconds: 250),
curve: Curves.ease,
);
}
The problem is, I am calling _toEnd()
function before the last item inserts in to the list. So, I am looking for a callback (if there is any) that tells me build()
is done. Then I call my _toEnd()
function.
What is the best practice in this case?
The async way from @creativecreatorormaybenot is enough to answer the question for most situations.
But if you want to
setState()
or do something that will change widgets in the tree right after building the widget, you cannot use the async way. Because the callback will be fired during the build process of the widget tree. It will throw an exception :For this situation, you can register a post frame callback to modify the widget:
General solution
Just to clear things up, I did not expect this question to attract so much attention. Hence, I only answered for this very specific case.
As explained in another answer
WidgetsBinding
offers a way to add a one time post frame callback.As this callback will only be called a single time, you will want to add it every time you build:
Specific (async)
Elaborating on Günter's comment:
There is a nice example illustrating that effect here.
Extensive information about scheduling in Dart can be found here.