riverpod_cache_engine 1.0.0
riverpod_cache_engine: ^1.0.0 copied to clipboard
A powerful, zero-boilerplate caching library for Riverpod with background garbage collection, auto-refresh mechanisms, and in-memory/persistent storage support.
example/lib/main.dart
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:riverpod_cache_engine/riverpod_cache_engine.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
// Initialize the library: Zero config needed! It will use InMemoryCacheStore by default.
await RiverpodCache.initialize(cleanupInterval: const Duration(seconds: 10));
runApp(const ProviderScope(child: MyApp()));
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(debugShowCheckedModeBanner: false, home: MyHome());
}
}
// ==========================================
// Example using the new Extensions Architecture
// ==========================================
/// A simple data model for testing
class UserProfile {
final String name;
final int age;
UserProfile({required this.name, required this.age});
Map<String, dynamic> toJson() => {'name': name, 'age': age};
factory UserProfile.fromJson(Map<String, dynamic> json) {
return UserProfile(name: json['name'] as String, age: json['age'] as int);
}
}
/// A Notifier that manages the User state
class UserNotifier extends Notifier<UserProfile?> {
@override
UserProfile? build() {
loadUserData();
return null;
}
/// Function to load data from cache or an external source (API)
Future<void> loadUserData() async {
// 1. Read from the cache
// Thanks to onNull and onExpired, the library will fetch the data whether it's missing or expired!
final cachedMap = await caches.read(
'user_profile_key',
options: CacheOptions(
ttl: const Duration(seconds: 5),
onExpired: () async {
debugPrint('Fetching user update from server (onExpired)...');
await Future.delayed(const Duration(seconds: 1));
return UserProfile(name: 'Updated Ahmed', age: 29).toJson();
},
onNull: () async {
debugPrint(
'Cache not found! Fetching for the first time (onNull)...',
);
await Future.delayed(const Duration(seconds: 1));
return UserProfile(name: 'New Ahmed', age: 28).toJson();
},
),
);
if (cachedMap != null) {
// 2. Update state
state = UserProfile.fromJson(cachedMap);
debugPrint('Screen updated from cache!');
}
}
/// Function to clear the cache manually
Future<void> clearCache() async {
await caches.delete('user_profile_key');
state = null;
debugPrint('Cache cleared!');
}
List<String> list = ['Ahmed', 'Khalid', 'Saeed'];
void setRandomName() async {
int a = Random().nextInt(list.length);
await caches.write(
'randomName',
{'randomName': list[a]},
options: CacheOptions(
ttl: const Duration(seconds: 10),
onExpired: () async {
int aa = Random().nextInt(list.length);
final result = {'randomName': list[aa]};
return result;
},
),
);
}
void getLastName() async {
final name = await caches.read('randomName');
print(name);
}
}
// Provide the Notifier
final userProvider = NotifierProvider<UserNotifier, UserProfile?>(
() => UserNotifier(),
);
class MyHome extends ConsumerWidget {
const MyHome({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final userState = ref.watch(userProvider);
final userNotifier = ref.read(userProvider.notifier);
return Scaffold(
appBar: AppBar(title: const Text('Riverpod Cache Extension')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
if (userState == null)
const Text('No data currently available')
else
Text(
'Name: ${userState.name} | Age: ${userState.age}',
style: const TextStyle(fontSize: 20),
),
const SizedBox(height: 20),
ElevatedButton(
onPressed: () => userNotifier.loadUserData(),
child: const Text('Load Data (Cache or Network)'),
),
const SizedBox(height: 10),
ElevatedButton(
onPressed: () => userNotifier.clearCache(),
style: ElevatedButton.styleFrom(
backgroundColor: Colors.redAccent,
),
child: const Text('Clear Cache'),
),
ElevatedButton(
onPressed: () => userNotifier.setRandomName(),
style: ElevatedButton.styleFrom(
backgroundColor: Colors.blueAccent,
),
child: const Text('Set Random Name'),
),
ElevatedButton(
onPressed: () => userNotifier.getLastName(),
style: ElevatedButton.styleFrom(backgroundColor: Colors.green),
child: const Text('Get Random Name'),
),
],
),
),
);
}
}