cached_builder 1.0.0
cached_builder: ^1.0.0 copied to clipboard
A smart FutureBuilder replacement with built-in caching, retry, and stale-while-revalidate strategies. Integrated with connectivity_plus_wrapper for smart network awareness.
import 'package:connectivity_plus_wrapper/connectivity_plus_wrapper.dart';
import 'package:flutter/material.dart';
import 'package:cached_builder/cached_builder.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
late ConnectivityWrapper connectivityWrapper;
bool _isInitialized = false;
@override
void initState() {
super.initState();
_initialize();
}
Future<void> _initialize() async {
connectivityWrapper = ConnectivityWrapper();
setState(() => _isInitialized = true);
}
@override
Widget build(BuildContext context) {
if (!_isInitialized) {
return const MaterialApp(home: Scaffold(body: Center(child: CircularProgressIndicator())));
}
return MaterialApp(
home: DefaultConnectivityWrapper(
connectivityWrapper: connectivityWrapper,
child: const PostsPage(),
),
);
}
}
class PostsPage extends StatelessWidget {
const PostsPage({super.key});
Future<List<Map<String, dynamic>>> _fetchPosts() async {
await Future.delayed(const Duration(seconds: 2));
return [
{'id': 1, 'title': 'First Post', 'body': 'This is the first post'},
{'id': 2, 'title': 'Second Post', 'body': 'This is the second post'},
];
}
@override
Widget build(BuildContext context) {
final connectivityWrapper = DefaultConnectivityWrapper.of(context)!.connectivityWrapper;
return Scaffold(
appBar: AppBar(title: const Text('Smart Cached Builder')),
body: CachedBuilder(
future: _fetchPosts,
connectivityWrapper: connectivityWrapper,
cachePolicy: const ConnectivityAwareCachePolicy(
expiry: Duration(minutes: 10),
staleWhileRevalidate: true,
aggressiveCachingWhenOffline: true,
offlineExpiry: Duration(hours: 24),
),
builder: (posts, isFromCache) => Column(
children: [
if (isFromCache)
Container(
padding: const EdgeInsets.all(8),
color: Colors.blue[50],
child: const Row(
children: [
Icon(Icons.cached, size: 16),
SizedBox(width: 8),
Text('Showing cached data'),
],
),
),
Expanded(
child: ListView.builder(
itemCount: posts.length,
itemBuilder: (context, index) {
final post = posts[index];
return ListTile(
title: Text(post['title']),
subtitle: Text(post['body']),
);
},
),
),
],
),
loading: const Center(child: CircularProgressIndicator()),
error: (error, retry, status) => Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
if (status == ConnectionStatus.disconnected)
const Icon(Icons.wifi_off, size: 64),
Text('Error: ${status?.description ?? error.toString()}'),
ElevatedButton(
onPressed: retry,
child: const Text('Try Again'),
),
],
),
),
),
);
}
}