I am having a Future that is fetching and populating users below
Future<List<User>> _fetchUsersListUsingLoop() async {
try {
var response = await http.get(
Uri.parse(
"https://api.json-generator.com/templates/Eh5AlPjYVv6C/data"),
headers: {
"Content-Type": "application/json",
"Authorization": "Bearer tltsp6dmnbif01jy9xfo9ssn4620u89xhuwcm5t3",
});
List<User> usersList = [];
for (var u in json.decode(response.body)) {
User user = User(u["email"], u["about"], u["name"], u["picture"],
u["index"], u["imageFetchType"]);
usersList.add(user);
}
return usersList;
} catch (e) {
log("FetchUsersListUsingLoopException $e");
rethrow;
}
}
And below is how i am using future
in FutureBuilder to call _fetchUsersListUsingLoop()
and then use ListView.builder inside RefreshIndicator to show users in the list
body: SizedBox(
child: FutureBuilder(
future: _fetchUsersListUsingLoop(),
builder: (BuildContext context, AsyncSnapshot asyncSnapshot) {
if (asyncSnapshot.data == null) {
return const Center(child: CircularProgressIndicator());
} else {
return RefreshIndicator(
// background color
backgroundColor: Colors.white,
// refresh circular progress indicator color
color: Colors.green,
onRefresh: _fetchUsersListUsingLoop(),
child: ListView.builder(
itemCount: asyncSnapshot.data.length,
itemBuilder: (BuildContext context, int index) {
return ListTile(
contentPadding: const EdgeInsets.all(10),
leading: CircleAvatar(
backgroundImage:
NetworkImage(asyncSnapshot.data[index].picture),
),
title: Text(asyncSnapshot.data[index].name),
subtitle: Text(
"${asyncSnapshot.data[index].email} \nUsing NetworkImage with backgroundImage"),
);
},
));
}
}),
),
I am getting The argument type 'Future<List<User>>' can't be assigned to the parameter type 'Future<void> Function()'.
error in this line onRefresh: _fetchUsersListUsingLoop(),
How can i be able to call _fetchUsersListUsingLoop()
again when i swipe down to refresh
Instead of calling _fetchUsersListUsingLoop
you should use setState
to cause a rebuild so that FutureBuilder
fetches the data again.
onRefresh: () => setState(() {})
That being said it's best to store your future in initState
and update this future when needed by calling setState
. This is from documentation:
The future must have been obtained earlier, e.g. during State.initState, State.didUpdateWidget, or State.didChangeDependencies. It must not be created during the State.build or StatelessWidget.build method call when constructing the FutureBuilder. If the future is created at the same time as the FutureBuilder, then every time the FutureBuilder's parent is rebuilt, the asynchronous task will be restarted.
Future<List<User>>? _usersFuture;
@override
void initState() {
super.initState();
_usersFuture = _fetchUsersListUsingLoop();
}
Then:
onRefresh: () {
setState(() {
_usersFuture = _fetchUsersListUsingLoop();
});
}