Skip to content

Instantly share code, notes, and snippets.

@callmephil
Last active September 8, 2023 08:02
Show Gist options
  • Save callmephil/b76195cc8f72ed019ae27fac7716a8ca to your computer and use it in GitHub Desktop.
Save callmephil/b76195cc8f72ed019ae27fac7716a8ca to your computer and use it in GitHub Desktop.
stream memory caching example for flutter/dart
import 'dart:async';
import 'dart:math';
/// {@template cache_client}
/// An in-memory cache client.
/// {@endtemplate}
class CacheClient {
/// {@macro cache_client}
CacheClient() : _cache = <String, Object>{};
final Map<String, Object> _cache;
final _cacheUpdatesController =
StreamController<Map<String, Object>>.broadcast();
/// Stream of cache updates, emitted whenever the cache is modified.
Stream<Map<String, Object>> get cacheUpdates =>
_cacheUpdatesController.stream;
/// Writes the provide [key], [value] pair to the in-memory cache.
void write<T extends Object>({required String key, required T value}) {
if (_cache[key] != value) {
_cacheUpdatesController.add(_cache); // Emit a cache update event
}
_cache[key] = value;
}
/// Looks up the value for the provided [key].
/// Defaults to `null` if no value exists for the provided key.
T? read<T extends Object>({required String key}) {
final value = _cache[key];
if (value is T) return value;
return null;
}
/// dispose the internal stream controller
void dispose() {
_cacheUpdatesController.close();
}
}
class Account {
const Account({required this.id, this.name});
final String id;
final int? name;
static const empty = Account(id: '');
}
class AuthRepository {
AuthRepository() {
Stream<int> watchCounter() async* {
while (true) {
await Future.delayed(const Duration(seconds: 1));
yield Random().nextInt(10000);
}
}
watchCounter().listen(
(event) => _cache.write(
key: userCacheKey,
value: Account(id: '1', name: event),
),
);
}
final CacheClient _cache = CacheClient();
static const userCacheKey = '__user_cache_key__';
Stream<Account> get user {
return _cache.cacheUpdates
.where((cache) => cache.containsKey(userCacheKey))
.map((cache) => cache[userCacheKey] as Account? ?? Account.empty);
}
void updateCache() {
_cache.write(
key: userCacheKey,
value: Account(id: '1', name: Random().nextInt(1000)));
}
}
void main() {
final authRepo = AuthRepository();
authRepo.user.listen((event) => print(event.name));
for (var i = 0; i < 10; i++) {
Future.delayed(Duration(seconds: i), () => authRepo.updateCache());
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment