flutter_api_cache 0.0.1 copy "flutter_api_cache: ^0.0.1" to clipboard
flutter_api_cache: ^0.0.1 copied to clipboard

A powerful, lightweight API response caching solution for Flutter with TTL, offline-first support, stale-while-revalidate, and Dio interceptor.

flutter_api_cache #

Pub Version License: MIT Build Status Pub Points

A powerful, lightweight API response caching solution for Flutter with TTL, offline-first support, stale-while-revalidate, and Dio interceptor.


Features #

  • ๐Ÿ—‚๏ธ 5 caching strategies โ€” cacheFirst, networkFirst, staleWhileRevalidate, networkOnly, cacheOnly
  • ๐Ÿ”Œ Dio interceptor with automatic caching โ€” drop-in, zero-boilerplate integration
  • โšก Dual-layer caching โ€” in-memory LRU cache + persistent disk storage via Hive
  • โฑ๏ธ Configurable TTL per endpoint โ€” fine-grained control over cache freshness
  • ๐Ÿ“ก Offline-first support โ€” automatic cache fallback on network errors
  • ๐Ÿ”„ Stale-while-revalidate with background refresh callback
  • ๐Ÿ”‘ Smart cache key generation using MD5 hashing
  • ๐Ÿงน LRU eviction by count, size, and TTL expiry
  • ๐ŸŽฏ Per-request and URL-based policy configuration
  • ๐Ÿš€ Force refresh support โ€” bypass cache on demand
  • ๐Ÿ“Š Cache statistics and manual invalidation

Installation #

Add flutter_api_cache to your pubspec.yaml:

dependencies:
  flutter_api_cache: ^0.0.1

Then run:

flutter pub get

Quick Start #

import 'package:dio/dio.dart';
import 'package:flutter_api_cache/flutter_api_cache.dart';

Future<void> main() async {
  // 1. Create and initialize the cache manager
  final cacheManager = ApiCacheManager(
    config: const CacheConfig(
      defaultTtlSeconds: 300,
      maxEntries: 500,
      enableLogging: true,
    ),
  );
  await cacheManager.init();

  // 2. Create Dio and attach the cache interceptor
  final dio = Dio(BaseOptions(baseUrl: 'https://api.example.com'));
  dio.interceptors.add(CacheInterceptor(cacheManager: cacheManager));

  // 3. Make requests โ€” caching is handled automatically
  final response = await dio.get('/users');
  print('From cache: ${response.extra['fromCache'] ?? false}');
}

Caching Strategies #

Strategy Behavior Best For
cacheFirst Returns cache if available and fresh, otherwise fetches from network. Mostly static data
networkFirst Always tries network first, falls back to cache on failure. Frequently updated data
staleWhileRevalidate Returns cache immediately (even if stale), refreshes in background. Feeds and lists
networkOnly Always fetches from network, never uses or stores cache. Auth, payments
cacheOnly Only returns cached data, never makes a network call. Offline mode

Advanced Usage #

Per-Request Policy #

Override the default caching policy for a specific request using cachePolicyKey in request extras:

final response = await dio.get(
  '/users/1',
  options: Options(
    extra: {
      cachePolicyKey: const CachePolicy(
        strategy: CacheStrategy.networkFirst,
        ttlSeconds: 600,
      ),
    },
  ),
);

URL-Based Policy Map #

Configure different policies for different URL patterns via the interceptor's policyMap:

dio.interceptors.add(
  CacheInterceptor(
    cacheManager: cacheManager,
    policyMap: {
      '/users': const CachePolicy(
        strategy: CacheStrategy.cacheFirst,
        ttlSeconds: 300,
      ),
      '/config': const CachePolicy(
        strategy: CacheStrategy.cacheFirst,
        ttlSeconds: 3600, // Config rarely changes
      ),
      '/feed': const CachePolicy(
        strategy: CacheStrategy.staleWhileRevalidate,
        ttlSeconds: 60,
      ),
      '/auth': CachePolicy.none, // Never cache auth endpoints
    },
  ),
);

Force Refresh #

Bypass the cache and fetch fresh data from the network:

final response = await dio.get(
  '/users',
  options: Options(
    extra: {
      cachePolicyKey: const CachePolicy(forceRefresh: true),
    },
  ),
);

Background Update Callback #

React to background refreshes when using the stale-while-revalidate strategy:

cacheManager.onBackgroundUpdate = (key, entry) {
  print('Background refresh completed for: $key');
  // Update your UI here when fresh data arrives
};

Manual Cache Operations #

// Invalidate a specific endpoint
await cacheManager.invalidate('https://api.example.com/users/1');

// Invalidate all entries matching a predicate
await cacheManager.invalidateWhere((key) => key.contains('users'));

// Clear the entire cache
await cacheManager.clearAll();

// Get cache statistics
final stats = await cacheManager.getStats();
print(stats); // CacheStats(entries: 42, size: 0.15 MB, memory: 12)

// Dispose when done
await cacheManager.dispose();

Custom Storage Backend #

Implement the CacheStorage abstract class to provide your own storage backend (e.g. SQLite, shared preferences, or a remote cache). Pass your custom implementation as the diskStorage parameter when creating ApiCacheManager.

final cacheManager = ApiCacheManager(
  diskStorage: MyCustomStorage(),
);

Configuration #

final cacheManager = ApiCacheManager(
  config: const CacheConfig(
    defaultTtlSeconds: 300,    // Default TTL: 5 minutes
    maxEntries: 500,           // Max cached entries before LRU eviction
    maxSizeBytes: 0,           // Max cache size in bytes (0 = unlimited)
    enableLogging: false,      // Print cache operations to console
    boxName: 'flutter_api_cache', // Hive box name for disk storage
    useMemoryCache: true,      // Enable in-memory LRU cache layer
    maxMemoryEntries: 100,     // Max entries in the memory cache
  ),
);

How It Works #

  1. Request arrives โ†’ the Dio interceptor resolves the caching policy and checks the cache.
  2. Cache hit โ†’ the cached response is returned immediately, skipping the network call.
  3. Cache miss โ†’ the request is forwarded to the network; the response is cached on success.
  4. Network error โ†’ the interceptor falls back to stale cached data when available.
  5. Background โ†’ the eviction manager periodically cleans expired entries and enforces count/size limits.

Contributing #

Contributions are welcome! To get started:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/my-feature)
  3. Make your changes and write tests
  4. Ensure all checks pass before submitting:
    dart analyze
    dart format .
    flutter test
    
  5. Submit a pull request

License #

This project is licensed under the MIT License โ€” see the LICENSE file for details.

0
likes
130
points
0
downloads

Publisher

unverified uploader

Weekly Downloads

A powerful, lightweight API response caching solution for Flutter with TTL, offline-first support, stale-while-revalidate, and Dio interceptor.

Repository (GitHub)
View/report issues

Topics

#cache #api #dio #offline-first #http

Documentation

API reference

License

MIT (license)

Dependencies

connectivity_plus, crypto, dio, flutter, hive_flutter

More

Packages that depend on flutter_api_cache