为什么在ListView中滚动时,FutureBuilder会被多次调用?
为什么在ListView中滚动时,FutureBuilder会被多次调用?
我有一个ListView,其中包含FutureBuilder和ListView.Builder作为子项。在FutureBuilder中,我有一个ListView。问题是,当我滚动ListView父控件时,为什么FutureBuilder会再次重建?
您可以在此处查看我如何重现此问题:https://youtu.be/OKjiMOSJmYA
import 'package:flutter/material.dart';
class DebugScreen extends StatefulWidget {
@override
_DebugScreenState createState() => _DebugScreenState();
}
class _DebugScreenState extends State
List
var futureData;
var futureBuilderHelloWorld;
Future> getFutureData() async {
print("getFutureData");
var numbers = [
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
];
await Future.delayed(Duration(seconds: 3));
return await numbers;
}
@override
void initState() {
futureData = getFutureData();
futureBuilderHelloWorld = FutureBuilder(
future: futureData,
builder: (context, AsyncSnapshot> snapshot) {
print("future builder"); // 为什么滚动时会调用此处
switch (snapshot.connectionState) {
case ConnectionState.none:
case ConnectionState.waiting:
return Center(
child: CircularProgressIndicator(),
);
default:
if (snapshot.hasError) {
return Text("Error: " + snapshot.error.toString());
} else {
var numbers = snapshot.data;
return Container(
height: 190.0,
child: ListView.builder(
shrinkWrap: true,
itemCount: numbers.length,
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.all(16.0),
child: Text("Hello world ${numbers[index]}"),
);
},
),
);
}
}
},
);
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Debug Mode"),
),
body: ListView(
children:
futureBuilderHelloWorld,
ListView(
shrinkWrap: true,
physics: ClampingScrollPhysics(),
children: List.generate(100, (index) {
return Text("Flutter $index");
}).toList(),
)
],
),
);
}
}
现在在控制台上显示的结果如下:
I/flutter (18634): future builder
I/flutter (18634): future builder
I/flutter (18634): future builder
I/flutter (18634): future builder
在Flutter中,当在ListView中滚动时,为什么FutureBuilder会被多次调用?这个问题的出现原因是因为Flutter的文档中指出,如果你的future发生了变化,build方法会被调用两次。具体来说,当新的future非空时,会产生以下形式的快照对:
new AsyncSnapshot
new AsyncSnapshot
而前者只有在旧的future非空时才会产生,后者只有在新的future非空时才会产生。
为了解决这个问题,你可以根据这个文档中的说明来适应你的代码,例如通过保持调用计数器并只在第二次调用时更新列表。你可以参考文档中的示例代码来实现这一点。
参考文档:https://api.flutter.dev/flutter/widgets/FutureBuilder-class.html