在 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>而不是一个List,有什么解决方法? 你在哪里打电话给sort?你需要在posts类字段上调用它 当我在 initState() 中调用 API 时,因为它是 Future> 我必须像 Future&lt;List&lt;Post&gt;&gt; list; 那样定义它,所以在我想要排序的按钮中,我获取The method 'sort' isn't defined for the type 'Future'. 【参考方案1】:

您可以在 Future 函数中移动您的 posts.sort((a, b) =&gt; 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&lt;Post&gt;' can't be assigned to the parameter type 'Future&lt;List&lt;Posts&gt;&gt;'.,所以我刚开始......谢谢! 不要在这里使用FutureBuilder 即使没有FutureBuilder 也无法正常工作.. posts 不为空,但列表中没有任何变化... 我已经更新了帖子。也许这对你有用?

以上是关于在 Flutter 中对未来列表进行排序的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Flutter 中对列表进行排序 [重复]

Flutte VS RN

如何在 Flutter 中对 DataTable 小部件上的 Future<List> 数据类型进行排序?

如何在 Dart 中对 List<File> 进行排序,最后使用 null 对象

如何在C#中对列表进行排序[重复]

在 C# 中对对象列表进行排序