/// Performance optimization usage examples /// /// This file demonstrates how to use all performance optimizations /// in the retail POS app. import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../config/image_cache_config.dart'; import '../constants/performance_constants.dart'; import '../utils/debouncer.dart'; import '../utils/performance_monitor.dart'; import '../utils/provider_optimization.dart'; import '../utils/responsive_helper.dart'; import '../widgets/optimized_cached_image.dart'; import '../widgets/optimized_grid_view.dart'; import '../widgets/optimized_list_view.dart'; // ============================================================================ // EXAMPLE 1: Optimized Product Grid // ============================================================================ class ProductGridExample extends ConsumerWidget { const ProductGridExample({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { // Watch only the products list (granular rebuild) final productsAsync = ref.watch(exampleProductsProvider); return productsAsync.when( data: (products) { if (products.isEmpty) { return const GridEmptyState( message: 'No products found', icon: Icons.inventory_2_outlined, ); } // Use optimized grid with automatic performance enhancements return ProductGridView( products: products, itemBuilder: (context, product, index) { // Wrapped in RepaintBoundary automatically return const ExampleProductCard(); }, onScrollEnd: () { // Load more products when scrolling near end // ref.read(exampleProductsProvider.notifier).loadMore(); }, ); }, loading: () => const GridLoadingState(itemCount: 6), error: (error, stack) => GridEmptyState( message: 'Failed to load products', icon: Icons.error_outline, onRetry: () { ref.invalidate(exampleProductsProvider); }, ), ); } } // ============================================================================ // EXAMPLE 2: Optimized Product Card with Cached Image // ============================================================================ class ExampleProductCard extends StatelessWidget { const ExampleProductCard({super.key}); @override Widget build(BuildContext context) { // Use const constructor for better performance return Card( elevation: 2, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Optimized cached image with automatic sizing Expanded( flex: 3, child: ClipRRect( borderRadius: const BorderRadius.vertical( top: Radius.circular(12), ), child: ProductGridImage( imageUrl: 'https://example.com/product.jpg', size: 150, ), ), ), // Product details const Expanded( flex: 2, child: Padding( padding: EdgeInsets.all(12.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'Product Name', style: TextStyle( fontSize: 14, fontWeight: FontWeight.w600, ), maxLines: 2, overflow: TextOverflow.ellipsis, ), SizedBox(height: 4), Text( '\$99.99', style: TextStyle( fontSize: 16, fontWeight: FontWeight.bold, color: Colors.green, ), ), ], ), ), ), ], ), ); } } // ============================================================================ // EXAMPLE 3: Search with Debouncing // ============================================================================ class ProductSearchExample extends ConsumerStatefulWidget { const ProductSearchExample({super.key}); @override ConsumerState createState() => _ProductSearchExampleState(); } class _ProductSearchExampleState extends ConsumerState { final _searchController = TextEditingController(); final _searchDebouncer = SearchDebouncer(); // 300ms debounce @override void dispose() { _searchController.dispose(); _searchDebouncer.dispose(); super.dispose(); } void _onSearchChanged(String query) { // Debounce search to avoid excessive API calls _searchDebouncer.run(() { // Update search provider // ref.read(searchQueryProvider.notifier).state = query; }); } @override Widget build(BuildContext context) { return TextField( controller: _searchController, onChanged: _onSearchChanged, decoration: const InputDecoration( hintText: 'Search products...', prefixIcon: Icon(Icons.search), border: OutlineInputBorder(), ), ); } } // ============================================================================ // EXAMPLE 4: Optimized Cart List with Performance Tracking // ============================================================================ class CartListExample extends ConsumerWidget { const CartListExample({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { // Watch only cart items (not entire cart state) final cartItems = ref.watchField( exampleCartProvider, (cart) => cart.items, ); if (cartItems.isEmpty) { return const ListEmptyState( message: 'Your cart is empty', icon: Icons.shopping_cart_outlined, ); } return CartListView( items: cartItems, itemBuilder: (context, item, index) { return const ExampleCartItemCard(); }, ); } } class ExampleCartItemCard extends StatelessWidget { const ExampleCartItemCard({super.key}); @override Widget build(BuildContext context) { return ListTile( leading: const CartItemThumbnail( imageUrl: 'https://example.com/product.jpg', size: 60, ), title: const Text('Product Name'), subtitle: const Text('\$99.99'), trailing: Row( mainAxisSize: MainAxisSize.min, children: [ IconButton( icon: const Icon(Icons.remove_circle_outline), onPressed: () { // Decrease quantity }, ), const Text('1'), IconButton( icon: const Icon(Icons.add_circle_outline), onPressed: () { // Increase quantity }, ), ], ), ); } } // ============================================================================ // EXAMPLE 5: Responsive Grid with Adaptive Layout // ============================================================================ class ResponsiveGridExample extends StatelessWidget { const ResponsiveGridExample({super.key}); @override Widget build(BuildContext context) { // Get responsive values final columns = context.gridColumns; final spacing = context.spacing; final padding = context.responsivePadding; return Padding( padding: padding, child: GridView.builder( gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: columns, crossAxisSpacing: spacing, mainAxisSpacing: spacing, childAspectRatio: PerformanceConstants.productCardAspectRatio, ), itemBuilder: (context, index) { return const RepaintBoundary( child: ExampleProductCard(), ); }, ), ); } } // ============================================================================ // EXAMPLE 6: Database Operations with Performance Tracking // ============================================================================ class DatabaseExample { Future loadProductsWithTracking() async { // Track async operation performance final products = await PerformanceMonitor().trackAsync( 'loadProducts', () async { // Simulated database query await Future.delayed(const Duration(milliseconds: 100)); return []; }, ); // Or use extension final categories = await _loadCategories().trackPerformance('loadCategories'); } Future> _loadCategories() async { await Future.delayed(const Duration(milliseconds: 50)); return ['Electronics', 'Clothing', 'Food']; } } // ============================================================================ // EXAMPLE 7: Provider with Granular Rebuilds // ============================================================================ // Provider example (would use riverpod_annotation in real app) final exampleProductsProvider = Provider>((ref) => []); final exampleCartProvider = Provider((ref) => ExampleCart.empty()); // Optimized consumer that only rebuilds when name changes class OptimizedConsumerExample extends ConsumerWidget { const OptimizedConsumerExample({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { // Only rebuilds when product count changes final productCount = ref.watchField( exampleProductsProvider, (products) => products.length, ); return Text('Products: $productCount'); } } // ============================================================================ // EXAMPLE 8: Image Cache Management // ============================================================================ class ImageCacheExample { Future clearCaches() async { // Clear all image caches await ImageOptimization.clearAllCaches(); } Future clearProductImages() async { // Clear only product images await ProductImageCacheManager().emptyCache(); } Future clearCategoryImages() async { // Clear only category images await CategoryImageCacheManager().emptyCache(); } Future getCacheSize() async { // Get total cache size return await ImageOptimization.getTotalCacheSize(); } } // ============================================================================ // EXAMPLE 9: Performance Monitoring // ============================================================================ class PerformanceMonitoringExample extends StatefulWidget { const PerformanceMonitoringExample({super.key}); @override State createState() => _PerformanceMonitoringExampleState(); } class _PerformanceMonitoringExampleState extends State { @override Widget build(BuildContext context) { return RebuildTracker( name: 'PerformanceExample', child: const Column( children: [ Text('This widget rebuild count is tracked'), ], ), ); } Future loadData() async { // Track performance await PerformanceMonitor().trackAsync( 'loadData', () async { await Future.delayed(const Duration(milliseconds: 200)); }, ); } void calculateTotal() { // Track synchronous operation final total = PerformanceMonitor().track( 'calculateTotal', () { return 99.99; }, ); } @override void dispose() { // Print performance summary before disposing PerformanceMonitor().printSummary(); RebuildTracker.printRebuildStats(); super.dispose(); } } // ============================================================================ // Models (for examples) // ============================================================================ class ExampleProduct { final String id; final String name; final double price; final String? imageUrl; const ExampleProduct({ required this.id, required this.name, required this.price, this.imageUrl, }); } class ExampleCart { final List items; const ExampleCart({required this.items}); factory ExampleCart.empty() => const ExampleCart(items: []); } class ExampleCartItem { final String productId; final String name; final double price; final int quantity; final String? imageUrl; const ExampleCartItem({ required this.productId, required this.name, required this.price, required this.quantity, this.imageUrl, }); }