dart - 如何防止 FutureBuilder 的重建,即使其潜在的未来没有改变
问题描述
在 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);
}
}
}
解决方案
对于其他有此错误的人,我使用AbdulRahmanAlHamali在 GitHub 上的解决方案解决了它。这是他的回答:
您好,我认为这里的问题是每次发出重建时都会调用 FutureBuilder 状态的 didUpdateWidget 。此函数检查旧的未来对象是否与新的不同,如果是,则重新触发 FutureBuilder。
为了解决这个问题,我们可以在构建函数之外的其他地方调用 Future。比如在initState中,把它保存在一个成员变量中,并将这个变量传递给FutureBuilder。
因此,而不是:
FutureBuilder( future: someFunction(), ....
我们本应该:
initState() { super.initState(); _future = SomeFunction(); }
接着
FutureBuilder( future: _future, ....
在这里找到原始线程。
推荐阅读
- javascript - 如何检测脚本是直接调用还是通过带有 yargs 的节点调用?
- django - 'ws = cat.get_workspace('rake_ereke')' 代码在本地工作,但在服务器上引发无法建立新连接:[Errno 110]
- php - 来自 AJAX 请求的分页无法正常工作——Laravel 5.6
- c++ - 从编译时已知的日历日期创建 `std::chrono::time_point`
- javascript - 如何在 javascript 中的地理定位应用程序中实现搜索功能
- apache - htaccess 使用参数重定向到新域
- javascript - 在 querySelectorAll() 中插入变量不起作用
- javascript - 当我使用 jquery 滚动窗口时试图获得警报
- vb.net - Visual basic 10.0 不支持异步方法或 lambda
- javascript - Mongoose 填充数组为空