Sorting a Future List in Flutter
You can move your posts.sort((a, b) => a.id.compareTo(b.id));
inside your Future function, before returning posts
. And change the setState, to change the state of a boolean, which sorts or not.
You can change like this:
//define a boolen
bool _isSorted =false;
Future<List<Post>> fetchPosts(bool sortORnot) async {
List<Post> posts = [];
final response = await http.get('https://jsonplaceholder.typicode.com/posts');
if (response.statusCode == 200) {
// If the server did return a 200 OK response,
// then parse the JSON.
var postsJson = jsonDecode(response.body);
for (int i = 0; i < postsJson.length; i++) {
posts.add(Post.fromJson(jsonDecode(response.body)[i]));
}
if (sortORnot) {posts.sort((a, b) => a.id.compareTo(b.id));}// this will sort only if you wanted your list sorted.
return posts;
} else {
// If the server did not return a 200 OK response,
// then throw an exception.
throw Exception('Failed to load posts');
}
}
Change your FutureBuilder
to this:
FutureBuilder<List<Post>>(
future:_isSorted? fetchPosts(true):fetchPosts(false),
builder: (context, snapshot) {
and setState
to this:
setState(() {
_isSorted = !_isSorted; //this flips the value whenever you press it.
});
Now, in your future builder, you should get the posts sorted, can you try this?
GrandMagus
Updated on December 28, 2022Comments
-
GrandMagus over 1 year
I've been looking for a solution to sort a list (ascending and descending)
On Button Press
inside of aFutureBuilder
, that is aFuture<List>
, but can't seem to understand how to define it as a List and then sort it on a button press. So I call the API, the API returns some dummy value, it's gets built in the Future Builder and in aListView.builder
, now I want sort the list by id (or by any type for that matter) but the method is not working because the list is null. The code:API Call for the dummy data:
Future<List<Post>> fetchPosts() async { List<Post> posts = []; final response = await http.get('https://jsonplaceholder.typicode.com/posts'); if (response.statusCode == 200) { // If the server did return a 200 OK response, // then parse the JSON. var postsJson = jsonDecode(response.body); for (int i = 0; i < postsJson.length; i++) { posts.add(Post.fromJson(jsonDecode(response.body)[i])); } return posts; } else { // If the server did not return a 200 OK response, // then throw an exception. throw Exception('Failed to load posts'); } }
The Future Builder:
List<Post> posts = []; /// if a define it like this, the value is always null Future<List<Post>> futurePosts; @override void initState() { super.initState(); futurePosts = fetchPosts(); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.white, body: SafeArea( child: SingleChildScrollView( scrollDirection: Axis.vertical, child: Column( children: [ MaterialButton(color: Colors.grey, onPressed: (){ // here I am setting set to compare the values of all IDs so it can be sorted ascending and descending by number of ID every time I press the button setState(() { posts.sort((a, b) => a.id.compareTo(b.id)); }); },), Container( height: 1000, child: FutureBuilder<List<Post>>( future: futurePosts, builder: (context, snapshot) { if (snapshot.hasData) { return ListView.builder( shrinkWrap: true, itemCount: snapshot.data.length, itemBuilder: (context, index) { return Text('${snapshot.data[index].id}') }, ); } else if (snapshot.hasError) { return Text("${snapshot.error}"); } return Container(); }, ),
But it seems my understanding and code is not working for me at this point. Any help is appreciated, thanks in advance!
-
pskink about 3 yearsseems you need a
StreamBuilder
instead ofFutureBuilder
as you show your data multiple times, in order to trigger thebuilder:
property callback you most likely would need aStreamController.add
method -
GrandMagus about 3 yearsOk, maybe you have a point, but does the sort method stays the same? That it is my question here, sorting, I can try with
StreamBuilder
... -
GrandMagus about 3 yearsThanks mate, but
The method 'sort' isn't defined for the type 'Future'.
, since I'm calling an API, it s a Future<List<Post>> and not a List<Post>, what's the workaround that? -
pskink about 3 yearswhere you call
sort
? you need to call it onposts
class field -
GrandMagus about 3 yearsWhen I call the API in
initState()
, since it is a Future<List<Post>> I have to define it like thatFuture<List<Post>> list;
so in the button where I want to sort, I getThe method 'sort' isn't defined for the type 'Future'.
-
GrandMagus about 3 years
Future<List<Posts>> list; var ctrl = StreamController(); @override void initState() { super.initState(); list = fetchPosts(); Future.delayed(Duration(seconds: 3), () => list).then(ctrl.add); }
-
GrandMagus about 3 yearsLet us continue this discussion in chat.
-
pskink about 3 yearsas you can see
fetchPosts
isasync
method but its return value is not used at all -
GrandMagus about 3 yearsYeah, I see that mate, thanks a lot! Now the question is, how should I implement it on ONE button, should I use a boolean value or not? I actually was close to the solution, but you left the chat, but thanks a lot again!
-
pskink about 3 yearsONE button? i think you could use
Switch
class, the docs say: "A material design switch. Used to toggle the on/off state of a single setting." - you can also useCheckbox
class -
GrandMagus about 3 yearsYeah, like a toggle button with the sort function, sort descending and ascending on single click. I will try with the Switch and let you know how it goes.
-
-
GrandMagus about 3 yearsI've tried it, but it's not working, when I print out the
_isSorted
it does change to true and false, but the list stays the same, it is not sorting by ID value. -
GrandMagus about 3 yearswhenever I click the button, sometimes it calls in the API and sometimes it doesn't:
I/flutter ( 5048): outside the builder: false I/flutter ( 5048): in the api: true I/flutter ( 5048): outside the builder: true I/flutter ( 5048): outside the builder: false I/flutter ( 5048): in the api: true
-
GrandMagus about 3 yearsThe problem is that I have a
FutureBuilder
so if I setfuture: posts
, it returnsThe argument type 'List<Post>' can't be assigned to the parameter type 'Future<List<Posts>>'.
, so I'm right at the beginning.. Thanks tho! -
ChessMax about 3 yearsDon't use
FutureBuilder
here. -
GrandMagus about 3 yearsEven without the
FutureBuilder
it is not working.. -
GrandMagus about 3 yearsThe
posts
is not empty but nothing is changing in the list... -
ChessMax about 3 yearsI've updated the post. Maybe that would work for you?