Reputation: 451
I created a release build of my scroll demo app using Flutter. I wonder why the listview scrolling of my app is NOT as smooth as the flutter gallery app. I used LG G5 for this test.
Here's a link to my app's demo
Edit: here is the code.
class ListViewSample extends StatelessWidget {
@override
Widget build(BuildContext buidContext) {
return new Container(
child: new Center(
child: new ListView(
children: createListTiles(),
),
)
);
}
List<Widget> createListTiles() {
List<Widget> tiles = <Widget>[];
for(int i = 0; i < 40; i++) {
int count = i + 1;
tiles.add(
new ListTile(
leading: new CircleAvatar(
child: new Text("$count"),
backgroundColor: Colors.lightGreen[700],
),
title: new Text("Title number $count"),
subtitle: new Text("This is the subtitle number $count"),
)
);
}
return tiles;
}
Do someone experience the same too?
Thanks!
Upvotes: 28
Views: 34035
Reputation: 267664
First, you should always try to use ListView.builder
whenever possible.
Second, you should set resamplingEnabled
flag if the problem occurs on devices that support a higher refresh rate for the input than the display itself. For example, the Pixel 4 input runs at 120 Hz while the display runs at 90 Hz. This mismatch can cause slow scrolling performance.
void main() {
GestureBinding.instance.resamplingEnabled = true; // Set this flag.
run(MyApp());
}
Upvotes: 9
Reputation: 525
Just use itemExtent: 2000,
(2000 here is example length of your list) using this the scrolling machinery can make use of the foreknowledge of the children's extent to save work.
Many people suggested that release mode will fix the issue but that's wrong. It shouldn't be. On a low performance phone I faced lagging of list view under 4 tabs.
Upvotes: 2
Reputation: 1768
If you don't want to use ListView.builder, because you need to have different widgets in a ListView, you can use Column wrapped in SingleChildScrollView, instead of a ListView, like this:
class ListViewSample extends StatelessWidget {
@override
Widget build(BuildContext buidContext) {
return new Container(
child: new Center(
child: new SingleChildScrollView(
child: Column()
children: <Widget>[
headerWidget(context: context, step: 'STEP 1', text: "Company data"),
MyTextFieldWidget(
type: prefix0.TextFieldType.Text,
labelText: 'Insured',
prefsKey: COMPANY_INSURED,
editable: false,
),
MyTextFieldWidget(
type: prefix0.TextFieldType.Text,
labelText: 'Address 1',
prefsKey: COMPANY_INSURED,
editable: false,
),
MyTextFieldWidget(
type: prefix0.TextFieldType.Text,
labelText: 'Address 2',
prefsKey: COMPANY_INSURED,
editable: false,
),
],)
),
)
);
}
This also will fix the scrolling behaviour.
Upvotes: 5
Reputation: 1
Flutter’s profile mode compiles and launches your application almost identically to release mode, but with just enough additional functionality to allow debugging performance problems. For example, profile mode provides tracing information to the profiling tools.
In Android Studio and IntelliJ, use the Run > Flutter Run main.dart in Profile Mode menu item.
Upvotes: 0
Reputation: 2092
Flutter is not that smooth with "Debug" build, it runs much smoother with "Release" build ( from command line run "flutter run --release"). Of course Iiro Krankka's answer will also increase the list's performance.
Upvotes: 59
Reputation: 5239
The problem with your code is that you're using the regular ListView
, which isn't appropriate for lists that have lots of items. All of those 40 widgets are kept in memory, which causes the janky scrolling experience you're suffering from.
If you have a large number or indefinite amount of items, you should be using ListView.builder instead. It builds only the visible list items on-demand, which makes it possible to have even larger lists scroll smoothly.
Here's a complete sample how you would migrate your list to use the builder approach:
import 'package:flutter/material.dart';
class ListViewSample extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new Scaffold(
body: new Center(
child: new ListView.builder(
itemCount: 200,
itemBuilder: (context, index) {
final count = index + 1;
return new ListTile(
leading: new CircleAvatar(
child: new Text("$count"),
backgroundColor: Colors.lightGreen[700],
),
title: new Text("Title number $count"),
subtitle: new Text("This is the subtitle number $count"),
);
},
),
),
);
}
}
Note that there's a lot of items, in this case 200, but the scrolling is still buttery smooth.
Upvotes: 36