如何防止 FutureBuilder 的重建,即使其潜在的未来没有改变

Posted

技术标签:

【中文标题】如何防止 FutureBuilder 的重建,即使其潜在的未来没有改变【英文标题】:How to prevent FutureBuilder's rebuilds even its underlying future does not change 【发布时间】:2019-09-04 11:54:24 【问题描述】:

在 Flutter 中,我得到了不需要的重建。在我的例子中,我使用 FutureBuilder 通过获取 db 结果来显示一个列表,这是一个未来并且依赖于查询参数。如果查询参数没有改变,我试图让 FutureBuilder 的未来不会改变,但是每次都调用 FutureBuilder 的构建器块。我怎样才能让 FutureBuilder 在它的未来不变的地方不重建自己。

下面是我的代码,每次 MusicList2 的父小部件构建时,MusicList2 都会重新构建,它的 FutureBuilder 也会重新构建。

class MusicList2 extends StatefulWidget 
  final MusicRowActionCallback onTapItem;
  final MusicRowActionCallback onDoubleTap;
  final MusicRowActionCallback onLongPressed;
  final String facetName;
  final String facetValue;
  const MusicList2(
      Key key,
        this.onTapItem,
        this.onDoubleTap,
        this.onLongPressed,
        this.facetName,
        this.facetValue) : super(key: key);
  @override
  State<StatefulWidget> createState() 

    return _MusicList2State();
  




class _MusicList2State extends State<MusicList2> 
  Future<List<Music>> loadMusicByFacet;
  @override
  Widget build(BuildContext context) 

    return FutureBuilder<List<Music>>(
      future:
        loadMusicByFacet,
      builder: (context, snapshot) 
        if (snapshot.data == null)
          return Center(child: CircularProgressIndicator(),);
        return ListView.builder(
          shrinkWrap: true,
          key: const ValueKey<String>('music-list'),
          itemCount: snapshot.data.length,
          itemBuilder: (BuildContext context, int index) 
            final random = Random();
            var i = random.nextInt(5);
            return MusicRow(
              avatarBgColor: colors[i],
              music: snapshot.data[index],
              onTap: widget.onTapItem,
              onDoubleTap: widget.onDoubleTap,
              onLongPressed: widget.onLongPressed,
            );
          ,
        );
      ,
    );
  

  @override
  void initState() 
    super.initState();
    loadMusicByFacet = MusicsDatabaseRepository.get.getMusicsByFacet(widget.facetName, widget.facetValue);
  
  @override
  void didUpdateWidget(MusicList2 oldWidget) 
    super.didUpdateWidget(oldWidget);
    if (oldWidget.facetValue != widget.facetValue || oldWidget.facetName != widget.facetName) 
      loadMusicByFacet = MusicsDatabaseRepository.get.getMusicsByFacet(widget.facetName, widget.facetValue);
    
  

【问题讨论】:

这可能会有所帮助 - medium.com/saugo360/… 不,正如我所提到的,我已经保证未来不会改变。这里的问题是即使未来没有改变也会调用构建器块 【参考方案1】:

对于其他遇到此错误的人,我使用 GitHub 上的AbdulRahmanAlHamali 解决方案解决了它。这是他的回答:

你好,我相信这里的问题是didUpdateWidget的 每次发出重建时都会调用 FutureBuilder 状态。 此函数检查旧的未来对象是否不同于 新的,如果是,则重新启动 FutureBuilder。

为了解决这个问题,我们可以在其他地方调用 Future 构建功能。例如在initState中,并保存在一个成员中 变量,并将此变量传递给 FutureBuilder。

所以不要有:

FutureBuilder(
  future: someFunction(),
  ....

我们应该有:

initState() 
  super.initState();
  _future = SomeFunction();

然后

FutureBuilder(
  future: _future,
  ....

找到原帖here。

【讨论】:

如果需要,你如何调用它? 我知道这不是一个有用的答案,但这确实取决于。我需要看看你的代码给你一个更好的答案,对不起

以上是关于如何防止 FutureBuilder 的重建,即使其潜在的未来没有改变的主要内容,如果未能解决你的问题,请参考以下文章

使用 yarn install 或 add 时防止包重建

Flutter 使用 FutureBuilder 检索列表中的数据

如何防止 setState 在颤振中重建

Xcode 在没有任何更改时重建项目

为啥 futureBuilder 返回一个空值?

FutureBuilder 构建函数不能返回 Null 错误