On my screen I need to display a ListView inside an other ListView. The screen can be summarized like this:
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Isolate FutureBuilder Example'),
),
body: Column(
children: [
Text("Header"),
SizedBox(height: 16),
Text("Filters"),
SizedBox(height: 32),
Expanded(
child: ListView.builder(
itemCount: 3,
itemBuilder: (context, index) {
return Column(
children: [
Text("List $index"),
SizedBox(height: 32),
ListView.builder(
shrinkWrap: true,
physics: const ClampingScrollPhysics(),
itemCount: 50,
itemBuilder: (context, index) {
print("building $index");
return Text("$index");
})
],
);
},
),
)
],
));
}
If you try it, you will se that all the 200 items of the inner ListView.builder
are built immediately, causing an UI jam in my main app since I have many more and more complex items.
How can I prevent this and keep the ListView
behavior that builds only the visible items? I read that shrinkWrap: true
can be the cause, but if I set it to false I have an error Vertical viewport was given unbounded height.
and I am not able to fix it
You can try this code
return Scaffold(
appBar: AppBar(
title: const Text('Isolate FutureBuilder Example'),
),
body: CustomScrollView(
physics: const ClampingScrollPhysics(),
slivers: [
const SliverAppBar(
title: Text('Isolate FutureBuilder Example'),
),
const SliverToBoxAdapter(
child: Column(
children: [
Text("Header"),
SizedBox(height: 16),
Text("Filters"),
SizedBox(height: 32),
],
),
),
...Iterable.generate(3, (index) {
return [
SliverToBoxAdapter(
child: Column(
children: [
Text("List $index"),
const SizedBox(height: 32),
],
),
),
SliverList.builder(
itemBuilder: (context, index) {
print("building $index");
return Text("$index");
},
itemCount: 50,
)
];
}).toList().expand((element) => element).toList()
],
),
);
}
here the nested list view is broken into flat listview using CustomScrollView and Slivers.