--- name: flutter-development description: Build beautiful cross-platform mobile apps with Flutter and Dart. Covers widgets, state management with Provider/BLoC, navigation, API integration, and material design. --- # Flutter Development ## Overview Create high-performance, visually stunning mobile applications using Flutter with Dart language. Master widget composition, state management patterns, navigation, and API integration. ## When to Use - Building iOS and Android apps with native performance - Designing custom UIs with Flutter's widget system - Implementing complex animations and visual effects - Rapid app development with hot reload - Creating consistent UX across platforms ## Instructions ### 1. **Project Structure & Navigation** ```dart // pubspec.yaml name: my_flutter_app version: 1.0.0 dependencies: flutter: sdk: flutter provider: ^6.0.0 http: ^1.1.0 go_router: ^12.0.0 // main.dart with GoRouter navigation import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return MaterialApp.router( title: 'Flutter App', theme: ThemeData(primarySwatch: Colors.blue, useMaterial3: true), routerConfig: _router, ); } } final GoRouter _router = GoRouter( routes: [ GoRoute( path: '/', builder: (context, state) => const HomeScreen(), routes: [ GoRoute( path: 'details/:id', builder: (context, state) => DetailsScreen( itemId: state.pathParameters['id']! ), ), ], ), GoRoute( path: '/profile', builder: (context, state) => const ProfileScreen(), ), ], ); ``` ### 2. **State Management with Provider** ```dart import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; import 'dart:convert'; class User { final String id; final String name; final String email; User({required this.id, required this.name, required this.email}); factory User.fromJson(Map json) { return User( id: json['id'], name: json['name'], email: json['email'], ); } } class UserProvider extends ChangeNotifier { User? _user; bool _isLoading = false; String? _error; User? get user => _user; bool get isLoading => _isLoading; String? get error => _error; Future fetchUser(String userId) async { _isLoading = true; _error = null; notifyListeners(); try { final response = await http.get( Uri.parse('https://api.example.com/users/$userId'), headers: {'Content-Type': 'application/json'}, ); if (response.statusCode == 200) { _user = User.fromJson(jsonDecode(response.body)); } else { _error = 'Failed to fetch user'; } } catch (e) { _error = 'Error: ${e.toString()}'; } finally { _isLoading = false; notifyListeners(); } } void logout() { _user = null; notifyListeners(); } } class ItemsProvider extends ChangeNotifier { List> _items = []; List> get items => _items; Future fetchItems() async { try { final response = await http.get( Uri.parse('https://api.example.com/items'), ); if (response.statusCode == 200) { _items = List>.from( jsonDecode(response.body) as List ); notifyListeners(); } } catch (e) { print('Error fetching items: $e'); } } } ``` ### 3. **Screens with Provider Integration** ```dart class HomeScreen extends StatefulWidget { const HomeScreen({Key? key}) : super(key: key); @override State createState() => _HomeScreenState(); } class _HomeScreenState extends State { @override void initState() { super.initState(); Future.microtask(() { Provider.of(context, listen: false).fetchItems(); }); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('Home Feed')), body: Consumer( builder: (context, itemsProvider, child) { if (itemsProvider.items.isEmpty) { return const Center(child: Text('No items found')); } return ListView.builder( itemCount: itemsProvider.items.length, itemBuilder: (context, index) { final item = itemsProvider.items[index]; return ItemCard(item: item); }, ); }, ), ); } } class ItemCard extends StatelessWidget { final Map item; const ItemCard({required this.item, Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Card( margin: const EdgeInsets.all(8), child: ListTile( title: Text(item['title'] ?? 'Untitled'), subtitle: Text(item['description'] ?? ''), trailing: const Icon(Icons.arrow_forward), onTap: () => context.go('/details/${item['id']}'), ), ); } } class DetailsScreen extends StatelessWidget { final String itemId; const DetailsScreen({required this.itemId, Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('Details')), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text('Item ID: $itemId', style: const TextStyle(fontSize: 18)), const SizedBox(height: 16), ElevatedButton( onPressed: () => context.pop(), child: const Text('Go Back'), ), ], ), ), ); } } class ProfileScreen extends StatelessWidget { const ProfileScreen({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('Profile')), body: Consumer( builder: (context, userProvider, child) { if (userProvider.isLoading) { return const Center(child: CircularProgressIndicator()); } if (userProvider.error != null) { return Center(child: Text('Error: ${userProvider.error}')); } final user = userProvider.user; if (user == null) { return const Center(child: Text('No user data')); } return Padding( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text('Name: ${user.name}', style: const TextStyle(fontSize: 18)), Text('Email: ${user.email}', style: const TextStyle(fontSize: 16)), const SizedBox(height: 16), ElevatedButton( onPressed: () => userProvider.logout(), child: const Text('Logout'), ), ], ), ); }, ), ); } } ``` ## Best Practices ### ✅ DO - Use widgets for every UI element - Implement proper state management - Use const constructors where possible - Dispose resources in state lifecycle - Test on multiple device sizes - Use meaningful widget names - Implement error handling - Use responsive design patterns - Test on both iOS and Android - Document custom widgets ### ❌ DON'T - Build entire screens in build() method - Use setState for complex state logic - Make network calls in build() - Ignore platform differences - Create overly nested widget trees - Hardcode strings - Ignore performance warnings - Skip testing - Forget to handle edge cases - Deploy without thorough testing