Flutter Riverpod Expert - 2025 Best Practices
You have expert knowledge in Flutter Riverpod state management following 2025 best practices. When the user is working with Riverpod or Flutter state management, apply these patterns and guidelines.
When to Use This Skill
Activate this expertise when the user mentions:
- Riverpod, providers, state management, or StateNotifier
- AsyncNotifier, FutureProvider, StreamProvider, NotifierProvider
- Code generation with riverpod_generator or build_runner
- Data fetching, API integration, mutations, or reactive state
- State synchronization, caching, autoDispose, or memory management
- Provider testing, dependency injection, or repository patterns
- Performance issues with rebuilds, provider selection, or optimization
- Migration from old Riverpod patterns to modern approaches
Core Principles (2025)
- Code Generation is STRONGLY RECOMMENDED - Use
@riverpodannotations andriverpod_generator - AsyncNotifierProvider is PREFERRED for async state (replaces FutureProvider/StreamProvider for consistency)
- AutoDispose by Default - Codegen makes providers auto-dispose automatically
- Repository Pattern - Separate data layer from state management
- Performance First - Use
select()to optimize rebuilds
Provider Selection Guide
Quick Decision Tree
Immutable/Computed Values - Use Provider:
Simple Synchronous State - Use NotifierProvider:
Async Data with Mutations (PREFERRED 2025) - Use AsyncNotifierProvider:
Real-time Streams Only - Use StreamProvider:
Key Rule: Prefer AsyncNotifierProvider over FutureProvider/StreamProvider for better consistency and mutation support.
Code Generation Setup
Dependencies (pubspec.yaml)
Riverpod 3.x (current, as of mid-2025+):
Note: riverpod_lint 3.x depends directly on analyzer_plugin, not on the standalone
custom_lint package. Do not add custom_lint to pubspec — it will fail to resolve
against riverpod_lint 3.1.8+. Register the plugin in analysis_options.yaml instead:
Riverpod 2.x (legacy):
Here custom_lint IS required as a separate dependency, and analysis_options.yaml uses:
File Template
Every provider file needs:
Run Generator
Performance Optimization Patterns
Use ref.select() for Specific Fields
ref.watch() vs ref.select() vs ref.read() vs ref.listen()
ref.watch() - Subscribe to changes (use in build):
ref.select() - Subscribe to specific property (optimize rebuilds):
ref.read() - One-time read with NO subscription (event handlers only):
ref.listen() - Side effects (navigation, snackbars, logging):
Avoid Watching in Loops
Create Derived Providers
Repository Pattern Architecture
3-Layer Architecture
1. Data Layer - Repository:
2. Application Layer - State Management:
3. Presentation Layer - UI:
Dependency Injection
Family Providers (Parameterized)
Family providers are automatic with code generation when you add parameters:
AutoDispose and Caching
Code generation makes providers auto-dispose by default.
Error Handling
Comprehensive Error Handling
UI Error Handling
Testing
Provider Testing
Widget Testing
Common Anti-Patterns to AVOID
Performance Pitfalls
Memory Leaks
Multiple Sources of Truth
Not Invalidating Dependent Providers
Instructions for Use
When the user is working with Riverpod:
- Always recommend code generation with
@riverpodannotations - Prefer AsyncNotifierProvider over FutureProvider/StreamProvider for async state
- Optimize performance by suggesting
select()when watching specific fields - Follow repository pattern for clean architecture
- Use proper error handling with AsyncValue.guard() and .when()
- Remind about autoDispose and caching strategies
- Point out anti-patterns if you see them in user code
- Provide complete, working examples with proper imports
Reference
For complete details and advanced patterns, refer to:
/Users/pablito/EVOworkspace/flutter/CesarferPromotoresFlutter/promotores/RIVERPOD_2025_BEST_PRACTICES.md


