So, I am learning to use the FutureBuilder class in Flutter
. My code works, but I wonder if I could improve the way I access the data from the snapshot.
My FutureBuilder
is like that:
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: FutureBuilder<List<ListCard>>(
future: items,
builder: (context, snapshot) {
return RefreshIndicator(
onRefresh: _pullRefresh,
child: _listView(snapshot),
);
},
),
),
);
}
items
is a class property of type Future<List<ListCard>>
. _listView
is the method where I work on the snapshot. There are 2 errors in this code:
Widget _listView(AsyncSnapshot<List<ListCard>> snapshot) {
if (snapshot.data != null) {
return ListView.builder(
itemCount: snapshot.data.length, // Error when accessing the length property
itemBuilder: (context, index) {
return snapshot.data[index]; // Error when accessing the index
},
);
} else {
return const Center(child: CircularProgressIndicator());
}
}
The two errors are actually the same. They say:
The property 'length' can't be unconditionally accessed because the receiver can be 'null'. Try making the access conditional (using '?.') or adding a null check to the target ('!').dart(unchecked_use_of_nullable_value)
I understand that snapshot.data
is of type List<ListCard>?
, therefore its value can either be null
or a list of type List<ListCard>
. In case the value is null, Flutter will display the CircularProcessIndicator
. If it's not null, then the ListView.builder
widget will be returned. If we reach that point, snapshot.data
is always a list (it's been tested in the if statement) and it should therefore have a length property.
I also tried:
Widget _listView(AsyncSnapshot<List<ListCard>> snapshot) {
if (snapshot.data is List<ListCard>) {
//...
}
but it gives exactly the same error. Same story with:
Widget _listView(AsyncSnapshot<List<ListCard>> snapshot) {
if (snapshot.hasData) {
//...
}
However I can get rid of these errors by adding the !
operator:
//...
itemCount: snapshot.data!.length,
itemBuilder: (context, index) {
return snapshot.data![index];
},
//...
I could also do a type assertion such as List<ListCard> data = snapshot.data as List<ListCard>;
but I don't want to go that way.
Is it possible to make this work without using the !
operator?
Thanks!