Reputation: 3570
In my Flutter project, I want to reposition a list on a screen, using the Positioned
widget, so the user can move the list manually or by using an animation.
What I did works pretty well, but I found out that, every time the list is moved, each item of the list is rebuild, which leads to some performance issues.
Here is a basic example:
class TestPositionedPage extends StatefulWidget {
@override
_TestPositionedPageState createState() => _TestPositionedPageState();
}
class _TestPositionedPageState extends State<TestPositionedPage> {
double _yPage = 0;
Widget _getItem(int position) {
print("get item at $position");
return ListTile(title: Text("Item at position $position"));
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Stack(
children: [
Align(
alignment: Alignment.topRight,
child: FlatButton(
onPressed: () {
setState(() => _yPage = Random().nextDouble() * 500);
},
child: Text("MOVE"),
color: Colors.redAccent,
),
),
Positioned(
left: 0,
top: _yPage,
child: Container(
width: 700,
height: 700,
child: ListView.builder(
itemCount: 100,
itemBuilder: (BuildContext context, int position) => _getItem(position),
),
),
),
],
),
),
);
}
}
In that example, there is a button and every time I click on the button, it randomly repositions the list. But every time the list is repositioned, here is what I see in the console:
I/flutter (17851): get item at 0
I/flutter (17851): get item at 1
I/flutter (17851): get item at 2
I/flutter (17851): get item at 3
I/flutter (17851): get item at 4
I/flutter (17851): get item at 5
I/flutter (17851): get item at 6
I/flutter (17851): get item at 7
I/flutter (17851): get item at 8
I/flutter (17851): get item at 9
I/flutter (17851): get item at 10
I/flutter (17851): get item at 11
I/flutter (17851): get item at 12
I/flutter (17851): get item at 13
I/flutter (17851): get item at 14
I/flutter (17851): get item at 15
I/flutter (17851): get item at 16
Which means that every time the list is repositioned, it's also rebuilt, even though nothing changed in the list.
So my question is: is there a way to prevent each item from being rebuilt every time the list is repositioned, or is there a way to cache the list rendering, in order to improve performances while repositioning?
Thanks.
Upvotes: 0
Views: 880
Reputation: 5052
When you call setState(() => _yPage = Random().nextDouble() * 500);
the whole tree is rebuilt again, which causing the list rebuilt too. Instead build the list one time and reuse required.
Widget _myList;
Widget initList(){
return ListView.builder(
itemCount: 100,
itemBuilder: (BuildContext context, int position) => _getItem(position),
);
}
@override
void initState() {
_myList = initList();
super.initState();
}
Then use the list in this way
Positioned(
left: 0,
top: _yPage,
child: Container(
width: 700,
height: 700,
child: _myList
...
Upvotes: 2