3.8 KiB
3.8 KiB
| name | description |
|---|---|
| best-practices-performance | Flutter performance best practices - optimization techniques, const usage, and performance patterns |
Performance Best Practices
Guidelines for optimizing Flutter app performance.
Use Const Constructors
Use const constructors to avoid unnecessary rebuilds.
// ✅ Good - const constructor
const Text('Hello')
// ❌ Bad - new instance on every build
Text('Hello')
// Use const widgets when values don't change
class MyWidget extends StatelessWidget {
const MyWidget({super.key});
@override
Widget build(BuildContext context) {
return const Column(
children: [
Text('Static text'),
Icon(Icons.star),
],
);
}
}
Minimize Widget Rebuilds
Split widgets to minimize rebuilds.
// ✅ Good - split widgets
class ParentWidget extends StatefulWidget {
@override
State<ParentWidget> createState() => _ParentWidgetState();
}
class _ParentWidgetState extends State<ParentWidget> {
int _counter = 0;
@override
Widget build(BuildContext context) {
return Column(
children: [
const ExpensiveWidget(), // const prevents rebuild
CounterDisplay(counter: _counter),
ElevatedButton(
onPressed: () => setState(() => _counter++),
child: const Text('Increment'),
),
],
);
}
}
Use ListView.builder
Use ListView.builder for efficient list rendering.
// ✅ Good - builds items on demand
ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) {
return ListTile(title: Text(items[index].name));
},
)
// ❌ Bad - builds all items at once
ListView(
children: items.map((item) => ListTile(
title: Text(item.name),
)).toList(),
)
Optimize Images
Optimize image loading and caching.
// Use cached_network_image package
CachedNetworkImage(
imageUrl: 'https://example.com/image.jpg',
placeholder: (context, url) => CircularProgressIndicator(),
errorWidget: (context, url, error) => Icon(Icons.error),
)
// Precache images
precacheImage(
AssetImage('assets/image.png'),
context,
);
Avoid Heavy Work in Build
Keep build methods lightweight.
// ❌ Bad - heavy computation in build
@override
Widget build(BuildContext context) {
final expensiveData = computeExpensiveData(); // Don't do this
return Text(expensiveData);
}
// ✅ Good - compute in initState or use FutureBuilder
@override
Widget build(BuildContext context) {
return FutureBuilder(
future: computeExpensiveData(),
builder: (context, snapshot) {
if (!snapshot.hasData) return CircularProgressIndicator();
return Text(snapshot.data);
},
);
}
Use Keys Appropriately
Use keys to preserve state.
// Use ValueKey for list items
ListView.builder(
itemBuilder: (context, index) => ListTile(
key: ValueKey(items[index].id),
title: Text(items[index].name),
),
)
RepaintBoundary
Isolate repaints to specific widgets.
RepaintBoundary(
child: AnimatedContainer(
duration: Duration(seconds: 1),
width: _width,
height: _height,
color: Colors.blue,
),
)
Profile Performance
Use Flutter DevTools to profile performance.
// Enable performance overlay
MaterialApp(
showPerformanceOverlay: true, // Debug only
// ...
)
Key Points
- Use
constconstructors whenever possible - Split widgets to minimize rebuilds
- Use
ListView.builderfor long lists - Optimize image loading and caching
- Keep build methods lightweight
- Use keys appropriately to preserve state
- Use
RepaintBoundaryto isolate repaints - Profile with Flutter DevTools
- Avoid unnecessary setState calls
- Use
constwidgets for static content