# Widget Patterns Flutter widget best practices covering const optimization, responsive layouts, hooks, and sliver patterns. ## Optimized Widget Pattern Always use `const` constructors for static widgets to prevent unnecessary rebuilds: ```dart class OptimizedCard extends StatelessWidget { final String title; final VoidCallback onTap; const OptimizedCard({ super.key, required this.title, required this.onTap, }); @override Widget build(BuildContext context) { return Card( child: InkWell( onTap: onTap, child: Padding( padding: const EdgeInsets.all(16), child: Text(title, style: Theme.of(context).textTheme.titleMedium), ), ), ); } } ``` ### Extracting Const Widgets ```dart class MyScreen extends StatelessWidget { const MyScreen({super.key}); @override Widget build(BuildContext context) { return Column( children: const [ _Header(), _Body(), _Footer(), ], ); } } class _Header extends StatelessWidget { const _Header(); @override Widget build(BuildContext context) { return const Text('Header'); } } ``` ## Responsive Layout ```dart class ResponsiveLayout extends StatelessWidget { final Widget mobile; final Widget? tablet; final Widget desktop; const ResponsiveLayout({ super.key, required this.mobile, this.tablet, required this.desktop, }); static const double mobileBreakpoint = 650; static const double desktopBreakpoint = 1100; @override Widget build(BuildContext context) { return LayoutBuilder( builder: (context, constraints) { if (constraints.maxWidth >= desktopBreakpoint) return desktop; if (constraints.maxWidth >= mobileBreakpoint) return tablet ?? mobile; return mobile; }, ); } } ``` ### Breakpoint Reference | Type | Width | Usage | |------|-------|-------| | Mobile | < 650pt | Single column, bottom nav | | Tablet | 650-1100pt | Two columns, side nav optional | | Desktop | > 1100pt | Multi-column, persistent nav | ## Custom Hooks (flutter_hooks) ```dart import 'package:flutter_hooks/flutter_hooks.dart'; class CounterWidget extends HookWidget { const CounterWidget({super.key}); @override Widget build(BuildContext context) { final counter = useState(0); final controller = useTextEditingController(); final isMounted = useIsMounted(); useEffect(() { debugPrint('Widget mounted'); return () { debugPrint('Widget disposed'); }; }, const []); return Column( children: [ Text('Count: ${counter.value}'), ElevatedButton( onPressed: () => counter.value++, child: const Text('Increment'), ), TextField(controller: controller), ], ); } } ``` ### Common Hooks | Hook | Purpose | |------|---------| | `useState` | Local state management | | `useEffect` | Side effects with cleanup | | `useMemoized` | Expensive computation caching | | `useTextEditingController` | Text field controller | | `useAnimationController` | Animation controller | | `useFocusNode` | Focus management | | `useIsMounted` | Check if widget is mounted | ## Sliver Patterns ```dart CustomScrollView( slivers: [ SliverAppBar( expandedHeight: 200, pinned: true, flexibleSpace: FlexibleSpaceBar( title: const Text('Title'), background: Image.network(imageUrl, fit: BoxFit.cover), ), ), SliverPadding( padding: const EdgeInsets.all(16), sliver: SliverList( delegate: SliverChildBuilderDelegate( (context, index) => ListTile( key: ValueKey(items[index].id), title: Text(items[index].title), ), childCount: items.length, ), ), ), const SliverToBoxAdapter( child: Padding( padding: EdgeInsets.all(16), child: Text('Footer'), ), ), ], ) ``` ### Sliver Types | Sliver | Usage | |--------|-------| | `SliverAppBar` | Collapsing app bar | | `SliverList` | Lazy list | | `SliverGrid` | Lazy grid | | `SliverToBoxAdapter` | Single non-sliver widget | | `SliverPadding` | Add padding to sliver | | `SliverFillRemaining` | Fill remaining space | ## Key Usage Patterns ```dart ListView.builder( itemCount: items.length, itemBuilder: (context, index) { final item = items[index]; return Dismissible( key: ValueKey(item.id), child: ListTile( key: ValueKey('tile_${item.id}'), title: Text(item.title), ), ); }, ) ``` | Key Type | When to Use | |----------|-------------| | `ValueKey` | Unique ID available | | `ObjectKey` | Object identity matters | | `UniqueKey` | Force rebuild | | `GlobalKey` | Access state across tree | ## Optimization Checklist | Pattern | Implementation | |---------|----------------| | const widgets | Add `const` to static widgets | | Keys | Use `ValueKey` for list items | | Select | `ref.watch(provider.select(...))` | | RepaintBoundary | Isolate expensive repaints | | ListView.builder | Lazy loading for lists | | const constructors | Always use when possible | --- *Flutter and Material Design are trademarks of Google LLC.*