【问题标题】:Sorting a Future List in Flutter在 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'.

标签: flutter sorting mobile flutter-layout


【解决方案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 不为空,但列表中没有任何变化...
  • 我已经更新了帖子。也许这对你有用?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-12-10
  • 2023-03-16
  • 2021-03-30
  • 2020-08-17
  • 1970-01-01
  • 1970-01-01
  • 2019-02-24
相关资源
最近更新 更多