Package: prf - Effortless local persistence with type safety and zero boilerplate. No repeated strings. No manual casting

A little follow up on a package I published here before, it improved a lot since then thanks to community feedback (: prf | Flutter package

No boilerplate. No repeated strings. No setup. Define your variables once, then get() and set() them anywhere with zero friction. prf makes local persistence faster, simpler, and easier to scale. Supports 20+ built-in types and includes utilities like persistent cooldowns, rate limiters and stats. Designed to fully replace raw use of SharedPreferences.

:high_voltage: Define β†’ Get β†’ Set β†’ Done

Just define your variable once β€” no strings, no boilerplate:

final username = Prf<String>('username');

Then get it:

final value = await username.get();

Or set it:

await username.set('Joey');

That’s it. You’re done. Works out of the box with all of these:

  • bool int double String num Duration DateTime BigInt Uri Uint8List (binary)
  • Also lists List<String> List<int> List<***> of all supported types!
  • JSON & enums

Special Services & Utilities:

  • :timer_clock: PrfCooldown β€” for managing cooldown periods (e.g. daily rewards, retry delays)
  • :fire: PrfStreakTracker β€” aligned streak tracker that resets if a period is missed (e.g. daily activity chains)
  • :receipt: PrfHistory β€” for managing recent-item history lists with max length, deduplication, and isolation-safe list storage (e.g. recent searches, watched videos)
  • :chart_increasing: PrfPeriodicCounter β€” auto-resetting counter for aligned time periods (e.g. daily tasks, hourly pings, weekly goals)
  • :hourglass_not_done: PrfRolloverCounter β€” sliding-window counter that resets a fixed duration after each activity (e.g. 10-minute retry window, actions per hour)
  • :bar_chart: PrfRateLimiter β€” token-bucket limiter for rate control (e.g. 1000 actions per 15 minutes)
  • :tear_off_calendar: PrfActivityCounter β€” multi-resolution activity tracker across hour/day/month/year (e.g. usage stats, user engagement heatmaps)

:pushpin: Code Comparison

Using SharedPreferences:

final prefs = await SharedPreferences.getInstance();
await prefs.setString('username', 'Joey');
final username = prefs.getString('username') ?? '';

Using prf with cached access (Prf<T>):

final username = Prf<String>('username');
await username.set('Joey');
final name = await username.get();

Using prf with isolate-safe access (PrfIso<T>):

final username = Prf<String>('username').isolated;
await username.set('Joey');
final name = await username.get();

All prf types support the following methods:

Method Description
get() Returns the current value (cached or from disk).
set(value) Saves the value and updates the cache (if applicable).
remove() Deletes the value from storage (and cache if applicable).
isNull() Returns true if the value is null.
getOrFallback(fallback) Returns the value or a fallback if null.
existsOnPrefs() Checks if the key exists in storage.
1 Like