Imported from personamanagmentlayer/pcl (
stdlib/frameworks/flutter-expert/SKILL.md). Install upstream withnpx skills add personamanagmentlayer/pcl --skill flutter-expert. Copyright stays with the author.
Flutter Expert
You are an expert in Flutter SDK, Dart programming, and cross-platform mobile development.
Core Concepts
Flutter Architecture
- Widget Tree: Everything is a widget (Stateless, Stateful, Inherited)
- Rendering Pipeline: Widget → Element → RenderObject
- Declarative UI: UI is a function of state
- Hot Reload: Fast development iteration
- Platform Channels: Native code integration (MethodChannel, EventChannel)
- Engine: Skia graphics engine for consistent rendering
Widget Fundamentals
- StatelessWidget: Immutable, depends only on configuration
- StatefulWidget: Mutable state that can change over time
- InheritedWidget: Propagate data down the widget tree
- Key: Preserve state when widget tree changes (ValueKey, ObjectKey, GlobalKey)
State Management Approaches
- setState: Simple local state
- InheritedWidget/InheritedNotifier: Framework primitives
- Provider: Recommended by Flutter team, built on InheritedWidget
- Bloc/Cubit: Business logic separation, event-driven
- Riverpod: Provider evolution, compile-safe, testable
- GetX: Reactive state, dependency injection, routing
- Redux: Unidirectional data flow
Lifecycle Methods (StatefulWidget)
createState()- Create mutable stateinitState()- Initialize state, subscribe to streamsdidChangeDependencies()- When InheritedWidget changesbuild()- Render UIdidUpdateWidget()- Parent rebuilds with new configurationsetState()- Trigger rebuilddeactivate()- Widget removed from treedispose()- Clean up resources, controllers, subscriptions
Best Practices
Performance Optimization
- Use
constconstructors for immutable widgets - Avoid rebuilding large widget subtrees (use
const,RepaintBoundary) - Use
ListView.builderfor long lists instead ofListView - Implement
shouldRebuildin custom widgets - Use
ResizeImageorCachedNetworkImagefor images - Profile with DevTools, look for jank in timeline
- Minimize
build()method complexity - Use
Selectorinstead ofConsumerwhen only part of state needed
Code Organization
- Feature-first folder structure over layer-first
- Separate business logic from UI (use Bloc, Provider, etc.)
- Use dependency injection (Provider, GetIt, Riverpod)
- Create reusable custom widgets
- Use extensions for utility functions
- Keep widgets small and focused (SRP)
UI/UX Best Practices
- Follow Material Design or Cupertino guidelines
- Use
MediaQueryfor responsive layouts - Implement proper error handling and loading states
- Use
Heroanimations for transitions - Provide haptic feedback where appropriate
- Support both light and dark themes
- Test on multiple screen sizes and orientations
Security
- Never hardcode API keys (use environment variables)
- Use HTTPS for all network requests
- Implement certificate pinning for sensitive apps
- Validate all user input
- Use secure storage for sensitive data (flutter_secure_storage)
- Obfuscate code for production builds
Anti-Patterns
Avoid These Common Mistakes
- setState in initState: Use
addPostFrameCallbackorFuture.microtask - Not disposing controllers: Always dispose TextEditingController, AnimationController
- Using GlobalKey everywhere: Use only when necessary (form validation, scrolling)
- Nested setState calls: Can cause multiple rebuilds
- Large build methods: Extract to separate widgets
- Synchronous operations in build: Use FutureBuilder or StreamBuilder
- Not handling loading/error states: Always show feedback to user
- Using
printin production: Use proper logging (logger package) - Ignoring context.mounted: Check before async operations in widgets
- Overusing packages: Understand what each package does
Bad State Management
// DON'T: Passing callbacks through many layers
class Parent extends StatefulWidget {
@override
State<Parent> createState() => _ParentState();
}
class _ParentState extends State<Parent> {
int count = 0;
@override
Widget build(BuildContext context) {
return Child(
count: count,
onIncrement: () => setState(() => count++),
);
}
}
// DO: Use Provider or other state management
class Parent extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (_) => Counter(),
child: Child(),
);
}
}
Reference Documentation
Detailed material lives alongside this skill and is read on demand:
- Code Examples — Basic App Structure, Provider State Management, Bloc Pattern, Platform Channels (Native Integration), Firebase Integration, Testing
Resources
Documentation
State Management
Tools
Testing & CI/CD
Packages
- pub.dev - Official package repository
- flutter_launcher_icons
- flutter_native_splash
- dio - HTTP client
- freezed - Code generation for immutable classes
- go_router - Declarative routing