I have a stateful widget whose state builds a ListView
. The ListView
gets its data from an http API. I am using a Future<void>
method called getData
to retrieve this data and populate a List<>
with it before calling setState
.
My question is where should I call getData
when this screen first launches? If I call it in initState()
, I get the following error in the debug console:
[VERBOSE-2:ui_dart_state.cc(198)] Unhandled Exception: dependOnInheritedWidgetOfExactType<_InheritedTheme>() or dependOnInheritedElement() was called before _EventListState.initState() completed.
If I wrap the call to getData
in a delayed Future
, I do not see the error. Here's my code:
class _EventListState extends State<EventList> {
Future<void> getData() async {
events = [];
events = await Network.getUsers(context);
setState(() {});
}
List<Event> events = [];
@override
initState() {
super.initState();
getData(); // this cause the error
// Future.delayed(Duration(seconds: 1), getData); // this works
}
@override
build(context) {
return PlatformScaffold(
iosContentPadding: true,
body: ListView.builder(
padding: const EdgeInsets.all(10),
physics: const AlwaysScrollableScrollPhysics(),
itemCount: events.length,
itemBuilder: (context, index) => Text(events[index].summary),
),
);
}
}
Forcing a delay to retrieve the data does not feel right, so is there a better way?
Use FutureBuilder.
List<Event> events = [];
@override
Widget build(BuildContext context) {
return FutureBuilder(
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
return PlatformScaffold(
iosContentPadding: true,
body: ListView.builder(
padding: const EdgeInsets.all(10),
physics: const AlwaysScrollableScrollPhysics(),
itemCount: events.length,
itemBuilder: (context, index) => Text(events[index].summary),
),
);
} else if (snapshot.hasError) {
return Center(child: Text('Error: ${snapshot.error}'));
} else {
return Center(child: Text('Please wait its loading...'));
}
},
future: getData(),
);
}
Future<void> getData() async {
events = [];
events = await Network.getUsers(context);
}