在 Flutter 中对未来列表进行排序
Posted
技术标签:
【中文标题】在 Flutter 中对未来列表进行排序【英文标题】:Sorting a Future List in Flutter 【发布时间】:2021-07-01 23:48:52 【问题描述】:我一直在寻找一种解决方案来对FutureBuilder
内的列表(升序和降序)On Button Press
进行排序,即Future<List>
,但似乎无法理解如何将其定义为列出然后按一下按钮对其进行排序。所以我调用API,API返回一些虚拟值,它在Future Builder和ListView.builder
中构建,现在我想按id(或任何类型)对列表进行排序,但该方法不起作用因为列表为空。代码:
虚拟数据的 API 调用:
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');
未来的建设者:
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();
,
),
但目前我的理解和代码似乎对我不起作用。任何帮助表示赞赏,在此先感谢!
【问题讨论】:
似乎您需要StreamBuilder
而不是FutureBuilder
,因为您多次显示数据,以便触发builder:
属性回调,您很可能需要StreamController.add
方法跨度>
好吧,也许你有一个观点,但排序方法是否保持不变?这是我的问题,排序,我可以尝试StreamBuilder
...
谢谢伙计,但是The method 'sort' isn't defined for the type 'Future'.
,因为我正在调用一个API,它是一个Future>而不是一个Listsort
?你需要在posts
类字段上调用它
当我在 initState()
中调用 API 时,因为它是 Future> 我必须像 Future<List<Post>> list;
那样定义它,所以在我想要排序的按钮中,我获取The method 'sort' isn't defined for the type 'Future'.
【参考方案1】:
您可以在 Future 函数中移动您的 posts.sort((a, b) => a.id.compareTo(b.id));
,然后返回 posts
。并更改 setState,以更改布尔值的状态,无论是否排序。
你可以这样改变:
//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');
将您的 FutureBuilder
更改为:
FutureBuilder<List<Post>>(
future:_isSorted? fetchPosts(true):fetchPosts(false),
builder: (context, snapshot)
和setState
这个:
setState(()
_isSorted = !_isSorted; //this flips the value whenever you press it.
);
现在,在您未来的构建器中,您应该对帖子进行排序,您可以试试这个吗?
【讨论】:
我试过了,但它不起作用,当我打印出_isSorted
时,它确实更改为true 和false,但列表保持不变,它不是按ID 值排序。
每当我点击按钮时,有时它会调用 API,有时它不会: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
【参考方案2】:
我认为这样的事情应该可行:
List<Post> posts;
@override
void initState()
super.initState();
fetchPosts().then((items)
setState(()
posts = items;
);
);
@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: ()
setState(()
if (posts != null)
posts = posts.toList();
posts.sort((a, b) => a.id.compareTo(b.id));
);
,
),
Container(
height: 1000,
child: (posts != null)
? ListView.builder(
shrinkWrap: true,
itemCount: posts.length,
itemBuilder: (context, index)
return Text('$posts[index].id');
,
)
: Container(),
)
]),
),
),
);
您的posts
字段始终为空,因为您从未将数据分配给该字段。这是主要问题。试试看。
【讨论】:
问题是我有一个FutureBuilder
,所以如果我设置future: posts
,它会返回The argument type 'List<Post>' can't be assigned to the parameter type 'Future<List<Posts>>'.
,所以我刚开始......谢谢!
不要在这里使用FutureBuilder
。
即使没有FutureBuilder
也无法正常工作..
posts
不为空,但列表中没有任何变化...
我已经更新了帖子。也许这对你有用?以上是关于在 Flutter 中对未来列表进行排序的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Flutter 中对 DataTable 小部件上的 Future<List> 数据类型进行排序?