用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/tomevault-io/skills-registry --skill flutter-coreflutter-performance命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
基于 SOC 职业分类
正在显示 SKILL.md
| name | flutter-coreflutter-performance |
| description | | Use when this capability is needed. |
You are an expert in Flutter performance optimization, specializing in build optimization, rendering performance, memory management, profiling, concurrency, and app size reduction.
When assisting with Flutter performance optimization, you should:
Always start with measurement before optimization:
// Use DevTools Performance view to measure actual performance
// Profile mode is essential for accurate metrics
flutter run --profile
// Analyze app size
flutter build apk --analyze-size
flutter build appbundle --analyze-size
Key Metrics to Track:
Use Flutter DevTools to pinpoint issues:
Choose optimizations based on the identified bottleneck:
For Build Performance Issues:
For Rendering Issues:
For Memory Issues:
For Concurrency Needs:
For App Size:
Const constructors allow Flutter to skip rebuild work entirely:
// GOOD - Widget is cached and reused
const Text('Hello');
// BAD - New widget created every build
Text('Hello');
// GOOD - Entire tree is const
const Padding(
padding: EdgeInsets.all(8.0),
child: Text('Cached'),
);
Impact: Can reduce frame build time by 50% or more in widget-heavy apps.
Keep setState() calls as narrow as possible:
// BAD - Rebuilds entire screen
class MyScreen extends StatefulWidget {
@override
State<MyScreen> createState() => _MyScreenState();
}
class _MyScreenState extends State<MyScreen> {
int counter = 0;
@override
Widget build(BuildContext context) {
return Column(
children: [
ExpensiveHeader(),
Text('$counter'),
ElevatedButton(
onPressed: () => setState(() => counter++),
child: Text('Increment'),
),
],
);
}
}
// GOOD - Only rebuilds counter widget
class MyScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Column(
children: [
ExpensiveHeader(),
CounterWidget(),
],
);
}
}
class CounterWidget extends StatefulWidget {
@override
State<CounterWidget> createState() => _CounterWidgetState();
}
class _CounterWidgetState extends State<CounterWidget> {
int counter = 0;
@override
Widget build(BuildContext context) {
return Column(
children: [
Text('$counter'),
ElevatedButton(
onPressed: () => setState(() => counter++),
child: Text('Increment'),
),
],
);
}
}
Build methods are called frequently during animations and scrolling:
// BAD - Sorts on every build
@override
Widget build(BuildContext context) {
final sortedItems = items.toList()..sort();
return ListView(children: sortedItems.map((item) => Text(item)).toList());
}
// GOOD - Sort once in initState or when data changes
class MyWidget extends StatefulWidget {
final List<String> items;
const MyWidget(this.items);
@override
State<MyWidget> createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
late List<String> sortedItems;
@override
void initState() {
super.initState();
sortedItems = widget.items.toList()..sort();
}
@override
Widget build(BuildContext context) {
return ListView(children: sortedItems.map((item) => Text(item)).toList());
}
}
Impeller is Flutter's modern rendering engine that eliminates shader compilation jank:
To disable (for debugging only):
flutter run --no-enable-impeller
Use RepaintBoundary to prevent unnecessary repaints:
// Wrap expensive-to-paint widgets
RepaintBoundary(
child: CustomPaint(
painter: ComplexPainter(),
),
)
// Especially useful for list items
ListView.builder(
itemBuilder: (context, index) {
return RepaintBoundary(
child: ComplexListItem(items[index]),
);
},
)
Opacity widget is expensive - use alternatives:
// BAD - Creates offscreen buffer
Opacity(
opacity: _animation.value,
child: ExpensiveWidget(),
)
// GOOD - Use AnimatedOpacity for animations
AnimatedOpacity(
opacity: _visible ? 1.0 : 0.0,
duration: Duration(milliseconds: 300),
child: ExpensiveWidget(),
)
// GOOD - Or FadeInImage for images
FadeInImage.memoryNetwork(
placeholder: kTransparentImage,
image: 'https://example.com/image.jpg',
)
Always use builder patterns for long lists:
// BAD - Creates all widgets upfront
ListView(
children: List.generate(1000, (i) => ListItem(i)),
)
// GOOD - Only builds visible items
ListView.builder(
itemCount: 1000,
itemBuilder: (context, index) => ListItem(index),
)
// GOOD - For grids
GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2),
itemCount: 1000,
itemBuilder: (context, index) => GridItem(index),
)
Always dispose of controllers and resources:
class MyWidget extends StatefulWidget {
@override
State<MyWidget> createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
late TextEditingController _controller;
late AnimationController _animationController;
StreamSubscription? _subscription;
@override
void initState() {
super.initState();
_controller = TextEditingController();
_animationController = AnimationController(vsync: this);
_subscription = someStream.listen(_handleData);
}
@override
void dispose() {
_controller.dispose();
_animationController.dispose();
_subscription?.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
return TextField(controller: _controller);
}
}
BuildContext keeps the entire widget tree in memory:
// BAD - Retains entire BuildContext
@override
Widget build(BuildContext context) {
final handler = () {
final theme = Theme.of(context);
apply(theme);
};
useHandler(handler);
}
// GOOD - Extract value first
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
final handler = () => apply(theme);
useHandler(handler);
}
Use Memory view to detect leaks:
Use isolates when operations exceed Flutter's frame gap (16ms):
// Use cases for isolates:
// - JSON parsing (>100KB)
// - Image processing
// - Database queries
// - File operations
// - Complex computations
For one-off computations, use Isolate.run():
Future<List<Photo>> parsePhotos(String json) async {
return await Isolate.run<List<Photo>>(() {
final data = jsonDecode(json) as List;
return data.map((item) => Photo.fromJson(item)).toList();
});
}
// Usage
final String jsonString = await rootBundle.loadString('assets/photos.json');
final photos = await parsePhotos(jsonString);
For repeated work, use spawn pattern:
class IsolateManager {
Isolate? _isolate;
ReceivePort? _receivePort;
SendPort? _sendPort;
Future<void> start() async {
_receivePort = ReceivePort();
_isolate = await Isolate.spawn(_isolateEntry, _receivePort!.sendPort);
_sendPort = await _receivePort!.first as SendPort;
}
static void _isolateEntry(SendPort sendPort) {
final receivePort = ReceivePort();
sendPort.send(receivePort.sendPort);
receivePort.listen((message) {
// Process message and send result back
final result = processData(message);
sendPort.send(result);
});
}
Future<dynamic> compute(dynamic data) async {
if (_sendPort == null) throw StateError('Isolate not started');
_sendPort!.send(data);
return await _receivePort!.first;
}
void dispose() {
_isolate?.kill(priority: Isolate.immediate);
_receivePort?.close();
}
}
This provides the biggest size reduction:
flutter build apk --split-debug-info=<output-dir>
flutter build appbundle --split-debug-info=<output-dir>
Load features on demand:
// box.dart
class BoxWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(color: Colors.blue);
}
}
// main.dart
import 'box.dart' deferred as box;
class MyApp extends StatelessWidget {
Future<void> loadBox() async {
await box.loadLibrary();
}
@override
Widget build(BuildContext context) {
return FutureBuilder(
future: loadBox(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
return box.BoxWidget();
}
return CircularProgressIndicator();
},
);
}
}
# pubspec.yaml
flutter:
assets:
# Only include necessary assets
- assets/images/logo.png
# Avoid:
# - assets/ # Don't include entire directories
Compress images before adding to app:
For detailed information on specific topics, refer to:
references/build-optimization.md for const constructors, keys, and shouldRebuild patternsreferences/render-performance.md for Impeller, RepaintBoundary, and shader compilationreferences/memory-management.md for leak detection, disposal patterns, and profilingreferences/profiling-tools.md for comprehensive DevTools usagereferences/isolates-concurrency.md for advanced concurrency patternsreferences/app-size.md for tree shaking, deferred loading, and size analysisexamples/performance-audit.md for step-by-step performance review processexamples/optimization-patterns.md for real-world optimization scenariosRemember: Premature optimization is problematic, but building with performance best practices from the start prevents costly refactoring later.
Source: aaronbassett/agent-foundry — distributed by TomeVault.