I'm investigating performance difference between ListView and ListView.builder in Flutter. Theory says ListView create all widget at once, while ListView.builder create when it's visible.
I checked with Devtool that it's true. ListView create all widgets and keep them in memory, but when I scroll ListView, Widget are disposed and created when they come visible/invisible, I mean when they are or not in screen.
How it can be possible? If all widgets in ListView are already in memory, why are created and disposed?
You can check this behaviour with this code:
void main() {
runApp(const MainApp());
}
class MainApp extends StatelessWidget {
const MainApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(home: PageOne());
}
}
class PageOne extends StatelessWidget {
const PageOne({super.key});
@override
Widget build(BuildContext context) {
final items = List.generate(500000, (index) => Item(value: index));
return Scaffold(
body: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
const SizedBox(height: 16),
ElevatedButton(
onPressed: () => Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ThirdPage(items: items),
)),
child: const Text('ListView'),
),
],
),
),
);
}
}
class ThirdPage extends StatelessWidget {
const ThirdPage({super.key, required this.items});
final List<Item> items;
@override
Widget build(BuildContext context) {
return Scaffold(
body: ListView(
children: items.map((e) => _Item(item: e)).toList(),
),
);
}
}
class _Item extends StatefulWidget {
const _Item({required this.item});
final Item item;
@override
State<_Item> createState() => _ItemState();
}
class _ItemState extends State<_Item> {
@override
void initState() {
super.initState();
print('Create widget ${widget.item.value}');
}
@override
void dispose() {
print('Delete widget ${widget.item.value}');
super.dispose();
}
@override
Widget build(BuildContext context) {
return Text('${widget.item.value}');
}
}
ListViewall the children are created at once and are never disposed, withListView.builderthey are created / disposed only when are visible / hiddenlistviewis created in a very very long screen ' while the user scrolls up and down , suppose it's placed in the bottom of that screen . so when you are at the top of that screen . it may be disposed and recreated when going down.ListViewyou have to pass a list with already created widgets, withListView.builderthey are created on demandbuild: "Building widget: ...". And you could add the classItem.