在Flutter中添加/删除项目时,如何强制ListView.builder刷新?

时间:2020-02-04 03:04:38

标签: listview flutter

我知道我可以在包含this.setState()的父状态小部件屏幕上使用ListView.builder来使ListView重建其列表。

问题是我使用另一个子状态小部件来构建每个ListView项。 Flutter文档说,只要遇到相同的小部件,树构建就会停止。这使得ListView内容不会重建。

如何在不指定键(全局键/本地键)之类的情况下强制ListView使所有子级“无效”并强制重建整个内容?

编辑:简化代码。

class PostList extends extends StatefulWidget {
    final UserModel user;
    PostList({ this.user }): super();
    @override
      _PostListState createState() => _PostListState();
}

class _PostListState extends State<PostList> {
    UserModel _user;
    List<PostModel> _posts;
    final _repository = Repository();

    @override
    void initState() {
      _user = widget.user;
      _repository.fetchPosts(userId: user.id)
        .then((response) => this.setState(() => _posts = response)
        .catchError((onError) => debugPrint(onError);
    }

    addNewRandomPost() {
      final newPost = PostModel(text: DateTime.now().millisecondsSinceEpoch.toString());
      this.setState(() => _posts = [newPost]..addAll(_posts ?? []));
    }


    @override
    Widget build(BuildContext context) {
      return Scaffold(appBar: AppBar(title: "Post list"),
        body: ListView.builder(
          itemCount: (_posts?.length ?? 0) + 1,
          itemBuilder: (context, index) {
            if (index == 0) 
              return RaisedButton(child: Text("Add new random post"), onPressed: addNewRandomPost);
            else if(_posts == null) 
              return Center(child: CircularProgressIndicator());
            else 
              return PostCard(post: _posts[index - 1]);
          }
        )
    }
}

class PostCard extends StatefulWidget {
  final PostModel post;
  PostCard ({ this.post }): super();
  @override
  _PostCardState createState() => _PostCardState();
}

class _PostCardState extends State<PostCard> {
  PostModel _post;
  @override
  void initState() {
    _post = widget.post;
  }

  @override
  Widget build(BuildContext context) => Card(child: 
    Padding(padding: EdgeInsets.all(10), child: Text(_post.text));
}

PostCard小部件显然还有更多的代码和用途,我有意将其作为有状态小部件而不是无状态小部件。但是我只是在这里简化了它,以表明即使使用此简单代码,只要点击“添加新随机帖子”,就可以:

  • 无论何时最初没有帖子,列表都会从仅显示圆形指示器转变为正确显示新帖子。
  • 但是只要那里有新帖(_posts不为空),如果我在列表的开头添加新帖,则已经创建的现有明信片不会更改。它仅在列表的底部添加新的明信片小部件,显示列表中的最后一个帖子,具有讽刺意味的是,第一个数据被推送到最后一个。因此,即使帖子的内容实际上彼此不同,所有的明信片都显示相同的数据。

五次单击按钮后,我期望什么:

[ Add new random post ]
1580789378
1580789373
1580789363
1580789349
1580789332

我得到的是

[ Add new random post ]
1580789332
1580789332
1580789332
1580789332
1580789332

1 个答案:

答案 0 :(得分:0)

您可以这样做

List your_data_container;
_yourDeleteMethod()async{
  *your way of deleting*
  if(response.statuscode == 200){
    _fetchListContent();
  }
}
_yourUpdateMethod()async{
  *your way of Updating*
  if(response.statuscode == 200){
    _fetchListContent();
  }
}
_fetchListContent()async{
  *your way of fetching*
  if(response.statuscode==200){
    fetched_data = json.decode(response.body);
    setState((){
      your_data_container = *fetched_data*;
    })
  }
}
ListView.builder(
  itemCount: your_data_container.length,
  itemBuilder: (context, index){
  return Container(
    width: screenWidth,
    height: screenHeight/15,
    child: Row(
      children: <Widget>[
        Expanded(
          child: Text(index.toString)
        ),
        IconButton(
          icon: Icon(Icons.delete, color: Colors.red)
          onPressed: (){
            _yourDeleteMethod();

          }
        ),
        IconButton(`
          icon: Icon(Icons.edit)
          onPressed: (){
            _yourUpdateMethod();
          }
        )
      ]
    )
  );
}
)

注意:ListView.builder应该在内部版本中或作为小部件使用,这只是为了告诉您这不是完整的代码