我目前正在开发Flutter应用程序,该应用程序使用许多REST API与服务器端进行通信。我面临一些与FutureBuilder小部件相关的性能问题,具体实现如下:
RefreshIndicator(
displacement: 100.0,
onRefresh: _refreshLastEntries,
child: FutureBuilder<List<Entry>> (
future: lastEntriesList,
builder: (context, snapshot) {
if(snapshot.hasError) print(snapshot.error);
if(snapshot.data == null) return Container();
else return ListView.builder(
controller: _controller,
itemCount: snapshot.data.length,
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.all(10.0),
child: EntryCard(entry: snapshot.data[index])
);
},
);
},
),
),
顺便说一句,在同一页面构建中,还有2个带有RefreshIndicator的FutureBuilder实现,它们都由PageView包裹。 Android Studio中的Flutter Performance选项卡显示平均值。在调试模式下为30帧/秒(有时<30)的fps。在发布模式下效果更好,但仍低于60 fps,我可以注意到动画效果不佳。
我知道问题(虽然不确定)是FutureBuilder尝试重建,只要AsyncSnapshot
有数据。但是我想不出更好的实现方法。刷新功能_refreshLastEntries()
实现为:
Future<Null> _refreshLastEntries() async {
setState(() {
lastEntriesList = fetchLastEntries(2);
});
return Future.delayed(Duration(milliseconds: 600));
}
fetchLastEntries(int)
仅用于获取数据并将其映射到某些EntryModel类中。
成功获取数据后,我尝试设置一个全局值,然后将其用于构建ListView,但是它不起作用。
如果有问题,我正在使用配备Snapdragon 835和Adreno 540的Xiaomi MI6测试此应用程序。
由于很难复制相同的版本,因此我不会将任何其他代码附加为整个PageView构建代码,谢谢!
答案 0 :(得分:1)
如果将来的状态不变,则FutureBuilder小部件不应重建。您的情况可能是
setState(() {
lastEntriesList = fetchLastEntries(2);
});
内部_refreshLastEntries()
导致未完成的将来进行重建,完成后将通过FutureBuilder进行另一次重建。
由于您使用的是RefreshIndicator,因此我认为您不需要FutureBuilder。在_refreshLastEntries()
内部进行异步工作,完成后,更新ListView.builder小部件。要更清楚:
//Declare lastEntriesList as a list
List<Entry> lastEntriesList;
Future<void> _refreshLastEntries() async {
return fetchLastEntries(2).then((lastEntries) {
setState(() {
lastEntriesList = lastEntries;
});
});
}
并如下修改您的子树:
RefreshIndicator(
displacement: 100.0,
onRefresh: _refreshLastEntries,
child: ListView.builder(
controller: _controller,
itemCount: lastEntriesList.length,
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.all(10.0),
child: EntryCard(entry: lastEntrieslist[index])
);
},
);,
)