How can I use async / HTTP data to return child widgets in IndexedWidgetBuilder?
I am receiving JSON data over HTTP and displaying it in a ListView. Since this is HTTP, everything is async.
Here's what I would like to do:
var index = new ListView.builder(
controller: _scrollController,
itemBuilder: (ctx, i) async {
_log.fine("loading post $i");
var p = await _posts[i];
return p == null ? new PostPreview(p) : null;
},
);
Unfortunately this doesn't work as IndexedWidgetBuilder needs to be synchronous. How do I use the future to create a child for the IndexedWidgetBuilder? There seems to be no way to wait for completion .
I used to load data into an array, and the IndexedWidgetBuilder function was only checking to see if the list items existed before returning the child widget.
var index = new ListView.builder(
controller: _scrollController,
itemBuilder: (ctx, i) {
_log.fine("loading post $i");
return _posts.length > i ? new PostPreview(_posts[i]) : null;
},
);
This works, but I would like to completely decouple the view from the data and request JSON asynchronously as needed.
It also seems, in my limited experience, as if it could be a common use case. Can an asynchronous version of IndexWidgetBuilder be added for flutter?
source to share
You can wait for asynchronous computations using FutureBuilder
. I would probably change yours PostPreview
to take Future
as a constructor argument and put there FutureBuilder
, but if you want to leave it PostPreview
as it is, here's how to change yours itemBuilder
.
var index = new ListView.builder(
controller: _scrollController,
itemBuilder: (ctx, i) {
return new FutureBuilder(
future: _posts[i],
builder: (context, snapshot) {
return snapshot.connectionState == ConnectionState.done
? new PostPreview(snapshot.data)
: new Container(); // maybe a show placeholder widget?
);
},
);
The best part FutureBuilder
is that it takes care of scenarios where the asynchronous request completes and your state has already been removed.
source to share