runable
This commit is contained in:
447
.archive/examples/performance_examples.dart
Normal file
447
.archive/examples/performance_examples.dart
Normal file
@@ -0,0 +1,447 @@
|
||||
/// 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<ExampleProduct>(
|
||||
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<ProductSearchExample> createState() =>
|
||||
_ProductSearchExampleState();
|
||||
}
|
||||
|
||||
class _ProductSearchExampleState extends ConsumerState<ProductSearchExample> {
|
||||
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<ExampleCartItem>(
|
||||
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<void> loadProductsWithTracking() async {
|
||||
// Track async operation performance
|
||||
final products = await PerformanceMonitor().trackAsync(
|
||||
'loadProducts',
|
||||
() async {
|
||||
// Simulated database query
|
||||
await Future.delayed(const Duration(milliseconds: 100));
|
||||
return <ExampleProduct>[];
|
||||
},
|
||||
);
|
||||
|
||||
// Or use extension
|
||||
final categories = await _loadCategories().trackPerformance('loadCategories');
|
||||
}
|
||||
|
||||
Future<List<String>> _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<List<ExampleProduct>>((ref) => []);
|
||||
final exampleCartProvider = Provider<ExampleCart>((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<void> clearCaches() async {
|
||||
// Clear all image caches
|
||||
await ImageOptimization.clearAllCaches();
|
||||
}
|
||||
|
||||
Future<void> clearProductImages() async {
|
||||
// Clear only product images
|
||||
await ProductImageCacheManager().emptyCache();
|
||||
}
|
||||
|
||||
Future<void> clearCategoryImages() async {
|
||||
// Clear only category images
|
||||
await CategoryImageCacheManager().emptyCache();
|
||||
}
|
||||
|
||||
Future<int> getCacheSize() async {
|
||||
// Get total cache size
|
||||
return await ImageOptimization.getTotalCacheSize();
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// EXAMPLE 9: Performance Monitoring
|
||||
// ============================================================================
|
||||
|
||||
class PerformanceMonitoringExample extends StatefulWidget {
|
||||
const PerformanceMonitoringExample({super.key});
|
||||
|
||||
@override
|
||||
State<PerformanceMonitoringExample> createState() =>
|
||||
_PerformanceMonitoringExampleState();
|
||||
}
|
||||
|
||||
class _PerformanceMonitoringExampleState
|
||||
extends State<PerformanceMonitoringExample> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return RebuildTracker(
|
||||
name: 'PerformanceExample',
|
||||
child: const Column(
|
||||
children: [
|
||||
Text('This widget rebuild count is tracked'),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> 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<ExampleCartItem> 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,
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user