Riverpod Adapter
The Riverpod adapter provides idiomatic, type-safe providers for Fasq using flutter_riverpod. It simplifies state management by integrating Fasq’s powerful caching and synchronization with Riverpod’s dependency injection and reactive patterns.
Why Fasq + Riverpod?
While Riverpod is excellent for managing application state, it doesn’t natively handle the complexities of “Server State” (data that lives on a server, is asynchronous, and needs caching). Fasq solves several key problems for Riverpod users:
- Professional Caching: Implements Stale-While-Revalidate (SWR), background refetching, and custom cache expiry (
staleTime) natively. - Simplified Mutations: Provides a dedicated
mutationProviderwith built-in loading/error states and an imperative API (.mutate()). - Offline Sync: Automatically queues mutations while offline and syncs them once the connection is restored.
- Infinite Pagination: High-level abstractions for infinite scrolling and cursor-based pagination that reduce boilerplate.
- Coordinated Invalidation: Easily invalidate specific queries or entire “tags” of data to keep your UI in sync after updates.
- Declarative Retries & Polling: Configure retry logic and polling intervals as simple declarations rather than manual timers.
- Standard Riverpod Experience: Returns
AsyncValue<T>, so it feels exactly like a standard Riverpod provider but with much more power.
Overview
The Riverpod adapter provides:
queryProvider- Creates queries that returnAsyncValue<T>infiniteQueryProvider- Handles paginated data withAsyncValuemutationProvider- Manages server-side operations with imperative callsPrefetchExtension- Extension onWidgetReffor easy prefetching- Full Dependency Injection - Uses
fasqClientProviderfor the underlying client
Installation
Add the adapter and Riverpod to your project:
flutter pub add fasq_riverpod flutter_riverpod[!NOTE] This adapter is built on top of the fasq core package, which will be added automatically as a dependency.
Basic Usage
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:fasq_riverpod/fasq_riverpod.dart';
// 1. Define your provider
final usersProvider = queryProvider<List<User>>(
'users'.toQueryKey(),
() => api.fetchUsers(),
options: QueryOptions(
staleTime: Duration(minutes: 5),
),
);
class UsersScreen extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
// 2. Watch the provider
final usersAsync = ref.watch(usersProvider);
// 3. Handle states using .when()
return usersAsync.when(
data: (users) => ListView.builder(
itemCount: users.length,
itemBuilder: (context, index) => ListTile(
title: Text(users[index].name),
),
),
loading: () => Center(child: CircularProgressIndicator()),
error: (error, stack) => Center(child: Text('Error: $error')),
);
}
}Key Features
Idiomatic Riverpod
Fasq Riverpod providers return Riverpod’s native AsyncValue<T>. This means you can use all the familiar patterns like .when(), .maybeWhen(), and AsyncValue.copyWithPrevious.
Compile-Safe & Type-Safe
Everything is strictly typed. If your fetch function returns Future<User>, your provider will be of type AutoDisposeAsyncNotifierProvider<..., User>, and ref.watch will return AsyncValue<User>.
Automatic Refetch & Background Sync
The providers automatically handle background refetching. When data is being updated in the background, AsyncValue preserves the previous data so your UI doesn’t flicker, while isLoading (or isRefreshing in Riverpod 2) correctly indicates the network activity.
Common Operations
Manual Refetching
Use the provider’s notifier to trigger a manual refetch:
ElevatedButton(
onPressed: () => ref.read(usersProvider.notifier).refetch(),
child: Text('Refresh'),
)Mutations
Mutations are triggered via the notifier’s mutate method:
final createUserProvider = mutationProvider<User, String>(
(name) => api.createUser(name),
);
// In your widget:
final mutation = ref.watch(createUserProvider);
ElevatedButton(
onPressed: mutation.isLoading
? null
: () => ref.read(createUserProvider.notifier).mutate('John Doe'),
child: Text('Create User'),
)Next Steps
queryProvider- Deep dive into standard queriesmutationProvider- Learn about server-side updatesinfiniteQueryProvider- Handle paginated data- Configuration - Global client and persistence setup
- Metadata Handling - Attach extra info for global side effects
- Circuit Breaker
- DevTools Integration
- Error Tracking
- Leak Detection
- Logging
- Metrics Exporters
- Security
- Prefetching - Warm up your cache