为什么在ListView中滚动时,FutureBuilder会被多次调用?

7 浏览
0 Comments

为什么在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 numbers = [1, 2, 3, 4, 5, 6, 7];

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

0
0 Comments

在Flutter中,当在ListView中滚动时,为什么FutureBuilder会被多次调用?这个问题的出现原因是因为Flutter的文档中指出,如果你的future发生了变化,build方法会被调用两次。具体来说,当新的future非空时,会产生以下形式的快照对:

new AsyncSnapshot.withData(ConnectionState.none, 'data of first future')

new AsyncSnapshot.withData(ConnectionState.waiting, 'data of second future')

而前者只有在旧的future非空时才会产生,后者只有在新的future非空时才会产生。

为了解决这个问题,你可以根据这个文档中的说明来适应你的代码,例如通过保持调用计数器并只在第二次调用时更新列表。你可以参考文档中的示例代码来实现这一点。

参考文档:https://api.flutter.dev/flutter/widgets/FutureBuilder-class.html

0