Reputation: 53
I have a custom widget with a futurebuilder which I want to use to load some data.
This is how it looks like:
class LoadOverlay extends StatefulWidget {
Widget child;
LoadOverlay({Key key, this.child}) : super(key: key);
@override
_LoadOverlayState createState() => _LoadOverlayState();
}
class _LoadOverlayState extends State<LoadOverlay> {
@override
Widget build(BuildContext context) {
return FutureBuilder(
future: Catalog.catalog.loadAsset(), //Here the csvString gets loaded
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasData)
return widget.child;
else {
return Scaffold(
body: Center(
child: CircularProgressIndicator(), //Tells the user that something is loading
),
);
}
}
);
}
}
And this is how i use it:
class _HomePageState extends State<HomePage> {
@override
Widget build(BuildContext context) {
return LoadOverlay(
child: Scaffold(
body: Center(
child: Text(Catalog.catalog.csvString), //This gets created to early
),
)
);
}
}
The Problem is that Text(Catalog.catalog.csvString)
gets loaded before the futurebuilder executes and because csvString hasn't finished i get an null error. If i put this into the LoadOverlay like this
if (snapshot.hasData)
Text(Catalog.catalog.csvString)
it works because the code gets only executed after the snapshot has data.
So how do I pass a Widget to the FutureBuilder that gets called and drawn AFTER the future was executed
Upvotes: 0
Views: 35
Reputation: 5423
You can pass an empty String
while csvString
is still null
.
child: Text(Catalog.catalog.csvString ?? ''),
OR
Assign an empty String
to csvString
when it is initialized.
String csvString = '';
Upvotes: 4
Reputation: 1080
A different solution could be to use a builder
property in your custom widget instead of a child
property. This would look like:
class LoadOverlay extends StatefulWidget {
Widget Function(BuildContext) builder;
LoadOverlay({Key key, this.builder}) : super(key: key);
@override
_LoadOverlayState createState() => _LoadOverlayState();
}
class _LoadOverlayState extends State<LoadOverlay> {
@override
Widget build(BuildContext context) {
return FutureBuilder(
future: Catalog.catalog.loadAsset(), //Here the csvString gets loaded
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasData)
return widget.builder(context);
else {
return Scaffold(
body: Center(
child: CircularProgressIndicator(), //Tells the user that something is loading
),
);
}
}
);
}
}
And you would use it like:
class _HomePageState extends State<HomePage> {
@override
Widget build(BuildContext context) {
return LoadOverlay(
builder: (context) => Scaffold(
body: Center(
child: Text(Catalog.catalog.csvString), //This gets created to early
),
)
);
}
}
This way your code which you inject into the builder
property gets only executed if the Future
is finished.
Upvotes: 1